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.

1234 lines
33 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. NTacls
  5. Abstract:
  6. This module implements the CSecurityAttribute class. It's job is to
  7. encapsulate the NT security descriptors as needed by Calais.
  8. Author:
  9. Doug Barlow (dbarlow) 1/24/1997
  10. Environment:
  11. Windows NT, Win32, C++ w/ Exceptions
  12. Notes:
  13. ?Notes?
  14. --*/
  15. #ifndef WIN32_LEAN_AND_MEAN
  16. #define WIN32_LEAN_AND_MEAN
  17. #endif
  18. #include <windows.h>
  19. #include <CalaisLb.h>
  20. const CSecurityDescriptor::SecurityId
  21. CSecurityDescriptor::SID_Null = { SECURITY_NULL_SID_AUTHORITY, 1, SECURITY_NULL_RID, 0 },
  22. CSecurityDescriptor::SID_World = { SECURITY_WORLD_SID_AUTHORITY, 1, SECURITY_WORLD_RID, 0 },
  23. CSecurityDescriptor::SID_Local = { SECURITY_LOCAL_SID_AUTHORITY, 1, SECURITY_LOCAL_RID, 0 },
  24. CSecurityDescriptor::SID_Owner = { SECURITY_CREATOR_SID_AUTHORITY, 1, SECURITY_CREATOR_OWNER_RID, 0 },
  25. CSecurityDescriptor::SID_Group = { SECURITY_CREATOR_SID_AUTHORITY, 1, SECURITY_CREATOR_GROUP_RID, 0 },
  26. CSecurityDescriptor::SID_Admins = { SECURITY_NT_AUTHORITY, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS },
  27. CSecurityDescriptor::SID_SrvOps = { SECURITY_NT_AUTHORITY, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_SYSTEM_OPS },
  28. CSecurityDescriptor::SID_DialUp = { SECURITY_NT_AUTHORITY, 1, SECURITY_DIALUP_RID, 0 },
  29. CSecurityDescriptor::SID_Network = { SECURITY_NT_AUTHORITY, 1, SECURITY_NETWORK_RID, 0 },
  30. CSecurityDescriptor::SID_Batch = { SECURITY_NT_AUTHORITY, 1, SECURITY_BATCH_RID, 0 },
  31. CSecurityDescriptor::SID_Interactive = { SECURITY_NT_AUTHORITY, 1, SECURITY_INTERACTIVE_RID, 0 },
  32. CSecurityDescriptor::SID_Service = { SECURITY_NT_AUTHORITY, 1, SECURITY_SERVICE_RID, 0 },
  33. CSecurityDescriptor::SID_System = { SECURITY_NT_AUTHORITY, 1, SECURITY_LOCAL_SYSTEM_RID, 0 },
  34. CSecurityDescriptor::SID_LocalService ={ SECURITY_NT_AUTHORITY, 1, SECURITY_LOCAL_SERVICE_RID, 0 },
  35. CSecurityDescriptor::SID_SysDomain = { SECURITY_NT_AUTHORITY, 1, SECURITY_BUILTIN_DOMAIN_RID, 0 };
  36. CSecurityDescriptor::CSecurityDescriptor()
  37. {
  38. m_pSD = NULL;
  39. m_pOwner = NULL;
  40. m_pGroup = NULL;
  41. m_pDACL = NULL;
  42. m_pSACL= NULL;
  43. m_fInheritance = FALSE;
  44. }
  45. CSecurityDescriptor::~CSecurityDescriptor()
  46. {
  47. if (m_pSD)
  48. delete m_pSD;
  49. if (m_pOwner)
  50. delete[] (LPBYTE)m_pOwner;
  51. if (m_pGroup)
  52. delete[] (LPBYTE)m_pGroup;
  53. if (m_pDACL)
  54. delete[] (LPBYTE)m_pDACL;
  55. if (m_pSACL)
  56. delete[] (LPBYTE)m_pSACL;
  57. }
  58. HRESULT CSecurityDescriptor::Initialize()
  59. {
  60. if (m_pSD)
  61. {
  62. delete m_pSD;
  63. m_pSD = NULL;
  64. }
  65. if (m_pOwner)
  66. {
  67. delete[] (LPBYTE)(m_pOwner);
  68. m_pOwner = NULL;
  69. }
  70. if (m_pGroup)
  71. {
  72. delete[] (LPBYTE)(m_pGroup);
  73. m_pGroup = NULL;
  74. }
  75. if (m_pDACL)
  76. {
  77. delete[] (LPBYTE)(m_pDACL);
  78. m_pDACL = NULL;
  79. }
  80. if (m_pSACL)
  81. {
  82. delete[] (LPBYTE)(m_pSACL);
  83. m_pSACL = NULL;
  84. }
  85. m_pSD = new SECURITY_DESCRIPTOR;
  86. if (!m_pSD)
  87. return E_OUTOFMEMORY;
  88. if (!InitializeSecurityDescriptor(m_pSD, SECURITY_DESCRIPTOR_REVISION))
  89. {
  90. HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  91. delete m_pSD;
  92. m_pSD = NULL;
  93. _ASSERTE(FALSE);
  94. return hr;
  95. }
  96. // Set the DACL to allow EVERYONE
  97. SetSecurityDescriptorDacl(m_pSD, TRUE, NULL, FALSE);
  98. return S_OK;
  99. }
  100. HRESULT CSecurityDescriptor::InitializeFromProcessToken(BOOL bDefaulted)
  101. {
  102. PSID pUserSid;
  103. PSID pGroupSid;
  104. HRESULT hr;
  105. Initialize();
  106. hr = GetProcessSids(&pUserSid, &pGroupSid);
  107. if (!FAILED(hr))
  108. hr = SetOwner(pUserSid, bDefaulted);
  109. if (!FAILED(hr))
  110. hr = SetGroup(pGroupSid, bDefaulted);
  111. if (pUserSid)
  112. delete[] (LPBYTE)(pUserSid);
  113. if (pGroupSid)
  114. delete[] (LPBYTE)(pGroupSid);
  115. if (FAILED(hr))
  116. return hr;
  117. return S_OK;
  118. }
  119. HRESULT CSecurityDescriptor::InitializeFromThreadToken(BOOL bDefaulted, BOOL bRevertToProcessToken)
  120. {
  121. PSID pUserSid;
  122. PSID pGroupSid;
  123. HRESULT hr;
  124. Initialize();
  125. hr = GetThreadSids(&pUserSid, &pGroupSid);
  126. if (HRESULT_CODE(hr) == ERROR_NO_TOKEN && bRevertToProcessToken)
  127. hr = GetProcessSids(&pUserSid, &pGroupSid);
  128. if (!FAILED(hr))
  129. hr = SetOwner(pUserSid, bDefaulted);
  130. if (!FAILED(hr))
  131. hr = SetGroup(pGroupSid, bDefaulted);
  132. if (pUserSid)
  133. delete[] (LPBYTE)(pUserSid);
  134. if (pGroupSid)
  135. delete[] (LPBYTE)(pGroupSid);
  136. if (FAILED(hr))
  137. return hr;
  138. return S_OK;
  139. }
  140. HRESULT CSecurityDescriptor::SetOwner(PSID pOwnerSid, BOOL bDefaulted)
  141. {
  142. _ASSERTE(m_pSD);
  143. // Mark the SD as having no owner
  144. if (!SetSecurityDescriptorOwner(m_pSD, NULL, bDefaulted))
  145. {
  146. HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  147. _ASSERTE(FALSE);
  148. return hr;
  149. }
  150. if (m_pOwner)
  151. {
  152. delete[] (LPBYTE)(m_pOwner);
  153. m_pOwner = NULL;
  154. }
  155. // If they asked for no owner don't do the copy
  156. if (pOwnerSid == NULL)
  157. return S_OK;
  158. // Make a copy of the Sid for the return value
  159. DWORD dwSize = GetLengthSid(pOwnerSid);
  160. m_pOwner = (PSID) new BYTE[dwSize];
  161. if (!m_pOwner)
  162. {
  163. // Insufficient memory to allocate Sid
  164. _ASSERTE(FALSE);
  165. return E_OUTOFMEMORY;
  166. }
  167. if (!CopySid(dwSize, m_pOwner, pOwnerSid))
  168. {
  169. HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  170. _ASSERTE(FALSE);
  171. delete[] (LPBYTE)(m_pOwner);
  172. m_pOwner = NULL;
  173. return hr;
  174. }
  175. _ASSERTE(IsValidSid(m_pOwner));
  176. if (!SetSecurityDescriptorOwner(m_pSD, m_pOwner, bDefaulted))
  177. {
  178. HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  179. _ASSERTE(FALSE);
  180. delete[] (LPBYTE)(m_pOwner);
  181. m_pOwner = NULL;
  182. return hr;
  183. }
  184. return S_OK;
  185. }
  186. HRESULT CSecurityDescriptor::SetGroup(PSID pGroupSid, BOOL bDefaulted)
  187. {
  188. _ASSERTE(m_pSD);
  189. // Mark the SD as having no Group
  190. if (!SetSecurityDescriptorGroup(m_pSD, NULL, bDefaulted))
  191. {
  192. HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  193. _ASSERTE(FALSE);
  194. return hr;
  195. }
  196. if (m_pGroup)
  197. {
  198. delete[] (LPBYTE)(m_pGroup);
  199. m_pGroup = NULL;
  200. }
  201. // If they asked for no Group don't do the copy
  202. if (pGroupSid == NULL)
  203. return S_OK;
  204. // Make a copy of the Sid for the return value
  205. DWORD dwSize = GetLengthSid(pGroupSid);
  206. m_pGroup = (PSID) new BYTE[dwSize];
  207. if (!m_pGroup)
  208. {
  209. // Insufficient memory to allocate Sid
  210. _ASSERTE(FALSE);
  211. return E_OUTOFMEMORY;
  212. }
  213. if (!CopySid(dwSize, m_pGroup, pGroupSid))
  214. {
  215. HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  216. _ASSERTE(FALSE);
  217. delete[] (LPBYTE)(m_pGroup);
  218. m_pGroup = NULL;
  219. return hr;
  220. }
  221. _ASSERTE(IsValidSid(m_pGroup));
  222. if (!SetSecurityDescriptorGroup(m_pSD, m_pGroup, bDefaulted))
  223. {
  224. HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  225. _ASSERTE(FALSE);
  226. delete[] (LPBYTE)(m_pGroup);
  227. m_pGroup = NULL;
  228. return hr;
  229. }
  230. return S_OK;
  231. }
  232. HRESULT CSecurityDescriptor::Allow(const SecurityId *psidPrincipal, DWORD dwAccessMask)
  233. {
  234. HRESULT hr = AddAccessAllowedACEToACL(&m_pDACL, psidPrincipal, dwAccessMask);
  235. if (SUCCEEDED(hr))
  236. {
  237. if (!SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE))
  238. hr = HRESULT_FROM_WIN32(GetLastError());
  239. }
  240. return hr;
  241. }
  242. HRESULT CSecurityDescriptor::Allow(LPCTSTR pszPrincipal, DWORD dwAccessMask)
  243. {
  244. HRESULT hr = AddAccessAllowedACEToACL(&m_pDACL, pszPrincipal, dwAccessMask);
  245. if (SUCCEEDED(hr))
  246. {
  247. if (!SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE))
  248. hr = HRESULT_FROM_WIN32(GetLastError());
  249. }
  250. return hr;
  251. }
  252. HRESULT CSecurityDescriptor::AllowOwner(DWORD dwAccessMask)
  253. {
  254. HRESULT hr = AddAccessAllowedACEToACL(&m_pDACL, dwAccessMask);
  255. if (SUCCEEDED(hr))
  256. {
  257. if (!SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE))
  258. hr = HRESULT_FROM_WIN32(GetLastError());
  259. }
  260. return hr;
  261. }
  262. HRESULT CSecurityDescriptor::Deny(const SecurityId *psidPrincipal, DWORD dwAccessMask)
  263. {
  264. HRESULT hr = AddAccessDeniedACEToACL(&m_pDACL, psidPrincipal, dwAccessMask);
  265. if (SUCCEEDED(hr))
  266. {
  267. if (!SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE))
  268. hr = HRESULT_FROM_WIN32(GetLastError());
  269. }
  270. return hr;
  271. }
  272. HRESULT CSecurityDescriptor::Deny(LPCTSTR pszPrincipal, DWORD dwAccessMask)
  273. {
  274. HRESULT hr = AddAccessDeniedACEToACL(&m_pDACL, pszPrincipal, dwAccessMask);
  275. if (SUCCEEDED(hr))
  276. {
  277. if (!SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE))
  278. hr = HRESULT_FROM_WIN32(GetLastError());
  279. }
  280. return hr;
  281. }
  282. HRESULT CSecurityDescriptor::Revoke(LPCTSTR pszPrincipal)
  283. {
  284. HRESULT hr = RemovePrincipalFromACL(m_pDACL, pszPrincipal);
  285. if (SUCCEEDED(hr))
  286. {
  287. if (!SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE))
  288. hr = HRESULT_FROM_WIN32(GetLastError());
  289. }
  290. return hr;
  291. }
  292. HRESULT CSecurityDescriptor::GetProcessSids(PSID* ppUserSid, PSID* ppGroupSid)
  293. {
  294. BOOL bRes;
  295. HRESULT hr;
  296. HANDLE hToken = NULL;
  297. if (ppUserSid)
  298. *ppUserSid = NULL;
  299. if (ppGroupSid)
  300. *ppGroupSid = NULL;
  301. bRes = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);
  302. if (!bRes)
  303. {
  304. // Couldn't open process token
  305. hr = HRESULT_FROM_WIN32(GetLastError());
  306. _ASSERTE(FALSE);
  307. return hr;
  308. }
  309. hr = GetTokenSids(hToken, ppUserSid, ppGroupSid);
  310. CloseHandle(hToken);
  311. return hr;
  312. }
  313. HRESULT CSecurityDescriptor::GetThreadSids(PSID* ppUserSid, PSID* ppGroupSid, BOOL bOpenAsSelf)
  314. {
  315. BOOL bRes;
  316. HRESULT hr;
  317. HANDLE hToken = NULL;
  318. if (ppUserSid)
  319. *ppUserSid = NULL;
  320. if (ppGroupSid)
  321. *ppGroupSid = NULL;
  322. bRes = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, bOpenAsSelf, &hToken);
  323. if (!bRes)
  324. {
  325. // Couldn't open thread token
  326. hr = HRESULT_FROM_WIN32(GetLastError());
  327. return hr;
  328. }
  329. hr = GetTokenSids(hToken, ppUserSid, ppGroupSid);
  330. CloseHandle(hToken);
  331. return hr;
  332. }
  333. HRESULT CSecurityDescriptor::GetTokenSids(HANDLE hToken, PSID* ppUserSid, PSID* ppGroupSid)
  334. {
  335. DWORD dwSize;
  336. HRESULT hr;
  337. PTOKEN_USER ptkUser = NULL;
  338. PTOKEN_PRIMARY_GROUP ptkGroup = NULL;
  339. if (ppUserSid)
  340. *ppUserSid = NULL;
  341. if (ppGroupSid)
  342. *ppGroupSid = NULL;
  343. if (ppUserSid)
  344. {
  345. // Get length required for TokenUser by specifying buffer length of 0
  346. GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize);
  347. hr = GetLastError();
  348. if (hr != ERROR_INSUFFICIENT_BUFFER)
  349. {
  350. // Expected ERROR_INSUFFICIENT_BUFFER
  351. _ASSERTE(FALSE);
  352. hr = HRESULT_FROM_WIN32(hr);
  353. goto failed;
  354. }
  355. ptkUser = (TOKEN_USER*) new BYTE[dwSize];
  356. if (!ptkUser)
  357. {
  358. // Insufficient memory to allocate TOKEN_USER
  359. _ASSERTE(FALSE);
  360. hr = E_OUTOFMEMORY;
  361. goto failed;
  362. }
  363. // Get Sid of process token.
  364. if (!GetTokenInformation(hToken, TokenUser, ptkUser, dwSize, &dwSize))
  365. {
  366. // Couldn't get user info
  367. hr = HRESULT_FROM_WIN32(GetLastError());
  368. _ASSERTE(FALSE);
  369. goto failed;
  370. }
  371. // Make a copy of the Sid for the return value
  372. dwSize = GetLengthSid(ptkUser->User.Sid);
  373. PSID pSid = (PSID) new BYTE[dwSize];
  374. if (!pSid)
  375. {
  376. // Insufficient memory to allocate Sid
  377. _ASSERTE(FALSE);
  378. hr = E_OUTOFMEMORY;
  379. goto failed;
  380. }
  381. if (!CopySid(dwSize, pSid, ptkUser->User.Sid))
  382. {
  383. hr = HRESULT_FROM_WIN32(GetLastError());
  384. _ASSERTE(FALSE);
  385. goto failed;
  386. }
  387. _ASSERTE(IsValidSid(pSid));
  388. *ppUserSid = pSid;
  389. delete[] (LPBYTE)(ptkUser);
  390. ptkUser = NULL;
  391. }
  392. if (ppGroupSid)
  393. {
  394. // Get length required for TokenPrimaryGroup by specifying buffer length of 0
  395. GetTokenInformation(hToken, TokenPrimaryGroup, NULL, 0, &dwSize);
  396. hr = GetLastError();
  397. if (hr != ERROR_INSUFFICIENT_BUFFER)
  398. {
  399. // Expected ERROR_INSUFFICIENT_BUFFER
  400. _ASSERTE(FALSE);
  401. hr = HRESULT_FROM_WIN32(hr);
  402. goto failed;
  403. }
  404. ptkGroup = (TOKEN_PRIMARY_GROUP*) new BYTE[dwSize];
  405. if (!ptkGroup)
  406. {
  407. // Insufficient memory to allocate TOKEN_USER
  408. _ASSERTE(FALSE);
  409. hr = E_OUTOFMEMORY;
  410. goto failed;
  411. }
  412. // Get Sid of process token.
  413. if (!GetTokenInformation(hToken, TokenPrimaryGroup, ptkGroup, dwSize, &dwSize))
  414. {
  415. // Couldn't get user info
  416. hr = HRESULT_FROM_WIN32(GetLastError());
  417. _ASSERTE(FALSE);
  418. goto failed;
  419. }
  420. // Make a copy of the Sid for the return value
  421. dwSize = GetLengthSid(ptkGroup->PrimaryGroup);
  422. PSID pSid = (PSID) new BYTE[dwSize];
  423. if (!pSid)
  424. {
  425. // Insufficient memory to allocate Sid
  426. _ASSERTE(FALSE);
  427. hr = E_OUTOFMEMORY;
  428. goto failed;
  429. }
  430. if (!CopySid(dwSize, pSid, ptkGroup->PrimaryGroup))
  431. {
  432. hr = HRESULT_FROM_WIN32(GetLastError());
  433. _ASSERTE(FALSE);
  434. goto failed;
  435. }
  436. _ASSERTE(IsValidSid(pSid));
  437. *ppGroupSid = pSid;
  438. delete[] (LPBYTE)(ptkGroup);
  439. ptkGroup = NULL;
  440. }
  441. return S_OK;
  442. failed:
  443. if (ptkUser)
  444. delete[] (LPBYTE)(ptkUser);
  445. if (ptkGroup)
  446. delete[] (LPBYTE)(ptkGroup);
  447. return hr;
  448. }
  449. HRESULT CSecurityDescriptor::GetCurrentUserSID(PSID *ppSid)
  450. {
  451. HANDLE tkHandle = NULL;
  452. if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &tkHandle))
  453. {
  454. TOKEN_USER *tkUser;
  455. DWORD tkSize;
  456. DWORD sidLength;
  457. // Call to get size information for alloc
  458. GetTokenInformation(tkHandle, TokenUser, NULL, 0, &tkSize);
  459. tkUser = (TOKEN_USER *) new BYTE[tkSize];
  460. if (NULL == tkUser)
  461. {
  462. CloseHandle(tkHandle);
  463. return E_OUTOFMEMORY;
  464. }
  465. // Now make the real call
  466. if (GetTokenInformation(tkHandle, TokenUser, tkUser, tkSize, &tkSize))
  467. {
  468. sidLength = GetLengthSid(tkUser->User.Sid);
  469. *ppSid = (PSID) new BYTE[sidLength];
  470. if (NULL != *ppSid)
  471. {
  472. memcpy(*ppSid, tkUser->User.Sid, sidLength);
  473. CloseHandle(tkHandle);
  474. delete[] (LPBYTE)(tkUser);
  475. return S_OK;
  476. }
  477. else
  478. {
  479. CloseHandle(tkHandle);
  480. delete[] (LPBYTE)(tkUser);
  481. return E_OUTOFMEMORY;
  482. }
  483. }
  484. else
  485. {
  486. CloseHandle(tkHandle);
  487. delete[] (LPBYTE)(tkUser);
  488. return HRESULT_FROM_WIN32(GetLastError());
  489. }
  490. }
  491. return HRESULT_FROM_WIN32(GetLastError());
  492. }
  493. HRESULT CSecurityDescriptor::GetPrincipalSID(LPCTSTR pszPrincipal, PSID *ppSid)
  494. {
  495. HRESULT hr;
  496. LPTSTR pszRefDomain = NULL;
  497. DWORD dwDomainSize = 0;
  498. DWORD dwSidSize = 0;
  499. SID_NAME_USE snu;
  500. // Call to get size info for alloc
  501. LookupAccountName(NULL, pszPrincipal, *ppSid, &dwSidSize, pszRefDomain, &dwDomainSize, &snu);
  502. hr = GetLastError();
  503. if (hr != ERROR_INSUFFICIENT_BUFFER)
  504. return HRESULT_FROM_WIN32(hr);
  505. pszRefDomain = new TCHAR[dwDomainSize];
  506. if (pszRefDomain == NULL)
  507. return E_OUTOFMEMORY;
  508. *ppSid = (PSID) new BYTE[dwSidSize];
  509. if (*ppSid != NULL)
  510. {
  511. if (!LookupAccountName(NULL, pszPrincipal, *ppSid, &dwSidSize, pszRefDomain, &dwDomainSize, &snu))
  512. {
  513. delete[] (LPBYTE)(*ppSid);
  514. *ppSid = NULL;
  515. delete[] pszRefDomain;
  516. return HRESULT_FROM_WIN32(GetLastError());
  517. }
  518. delete[] pszRefDomain;
  519. return S_OK;
  520. }
  521. delete[] pszRefDomain;
  522. return E_OUTOFMEMORY;
  523. }
  524. HRESULT CSecurityDescriptor::Attach(PSECURITY_DESCRIPTOR pSelfRelativeSD)
  525. {
  526. PACL pDACL = NULL;
  527. PACL pSACL = NULL;
  528. BOOL bDACLPresent, bSACLPresent;
  529. BOOL bDefaulted;
  530. PACL m_pDACL = NULL;
  531. ACCESS_ALLOWED_ACE* pACE;
  532. HRESULT hr;
  533. PSID pUserSid;
  534. PSID pGroupSid;
  535. hr = Initialize();
  536. if(FAILED(hr))
  537. return hr;
  538. // get the existing DACL.
  539. if (!GetSecurityDescriptorDacl(pSelfRelativeSD, &bDACLPresent, &pDACL, &bDefaulted))
  540. goto failed;
  541. if (bDACLPresent)
  542. {
  543. if (pDACL)
  544. {
  545. // allocate new DACL.
  546. if (!(m_pDACL = (PACL) new BYTE[pDACL->AclSize]))
  547. goto failed;
  548. // initialize the DACL
  549. if (!InitializeAcl(m_pDACL, pDACL->AclSize, ACL_REVISION))
  550. goto failed;
  551. // copy the ACES
  552. for (int i = 0; i < pDACL->AceCount; i++)
  553. {
  554. if (!GetAce(pDACL, i, (void **)&pACE))
  555. goto failed;
  556. if (!AddAccessAllowedAce(m_pDACL, ACL_REVISION, pACE->Mask, (PSID)&(pACE->SidStart)))
  557. goto failed;
  558. }
  559. if (!IsValidAcl(m_pDACL))
  560. goto failed;
  561. }
  562. // set the DACL
  563. if (!SetSecurityDescriptorDacl(m_pSD, m_pDACL ? TRUE : FALSE, m_pDACL, bDefaulted))
  564. goto failed;
  565. }
  566. // get the existing SACL.
  567. if (!GetSecurityDescriptorSacl(pSelfRelativeSD, &bSACLPresent, &pSACL, &bDefaulted))
  568. goto failed;
  569. if (bSACLPresent)
  570. {
  571. if (pSACL)
  572. {
  573. // allocate new SACL.
  574. if (!(m_pSACL = (PACL) new BYTE[pSACL->AclSize]))
  575. goto failed;
  576. // initialize the SACL
  577. if (!InitializeAcl(m_pSACL, pSACL->AclSize, ACL_REVISION))
  578. goto failed;
  579. // copy the ACES
  580. for (int i = 0; i < pSACL->AceCount; i++)
  581. {
  582. if (!GetAce(pSACL, i, (void **)&pACE))
  583. goto failed;
  584. if (!AddAccessAllowedAce(m_pSACL, ACL_REVISION, pACE->Mask, (PSID)&(pACE->SidStart)))
  585. goto failed;
  586. }
  587. if (!IsValidAcl(m_pSACL))
  588. goto failed;
  589. }
  590. // set the SACL
  591. if (!SetSecurityDescriptorSacl(m_pSD, m_pSACL ? TRUE : FALSE, m_pSACL, bDefaulted))
  592. goto failed;
  593. }
  594. if (!GetSecurityDescriptorOwner(m_pSD, &pUserSid, &bDefaulted))
  595. goto failed;
  596. if (FAILED(SetOwner(pUserSid, bDefaulted)))
  597. goto failed;
  598. if (!GetSecurityDescriptorGroup(m_pSD, &pGroupSid, &bDefaulted))
  599. goto failed;
  600. if (FAILED(SetGroup(pGroupSid, bDefaulted)))
  601. goto failed;
  602. if (!IsValidSecurityDescriptor(m_pSD))
  603. goto failed;
  604. return hr;
  605. failed:
  606. if (m_pDACL)
  607. delete[] (LPBYTE)(m_pDACL);
  608. if (m_pSD)
  609. delete[] (LPBYTE)(m_pSD);
  610. return E_UNEXPECTED;
  611. }
  612. HRESULT CSecurityDescriptor::AttachObject(HANDLE hObject)
  613. {
  614. HRESULT hr;
  615. DWORD dwSize = 0;
  616. PSECURITY_DESCRIPTOR pSD = NULL;
  617. GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
  618. DACL_SECURITY_INFORMATION, pSD, 0, &dwSize);
  619. hr = GetLastError();
  620. if (hr != ERROR_INSUFFICIENT_BUFFER)
  621. return HRESULT_FROM_WIN32(hr);
  622. pSD = (PSECURITY_DESCRIPTOR) new BYTE[dwSize];
  623. if (NULL==pSD)
  624. return E_OUTOFMEMORY;
  625. if (!GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
  626. DACL_SECURITY_INFORMATION, pSD, dwSize, &dwSize))
  627. {
  628. hr = HRESULT_FROM_WIN32(GetLastError());
  629. delete[] (LPBYTE)(pSD);
  630. return hr;
  631. }
  632. hr = Attach(pSD);
  633. delete[] (LPBYTE)(pSD);
  634. return hr;
  635. }
  636. HRESULT CSecurityDescriptor::CopyACL(PACL pDest, PACL pSrc)
  637. {
  638. ACL_SIZE_INFORMATION aclSizeInfo;
  639. LPVOID pAce;
  640. ACE_HEADER *aceHeader;
  641. if (pSrc == NULL)
  642. return S_OK;
  643. if (!GetAclInformation(pSrc, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation))
  644. return HRESULT_FROM_WIN32(GetLastError());
  645. // Copy all of the ACEs to the new ACL
  646. for (UINT i = 0; i < aclSizeInfo.AceCount; i++)
  647. {
  648. if (!GetAce(pSrc, i, &pAce))
  649. return HRESULT_FROM_WIN32(GetLastError());
  650. aceHeader = (ACE_HEADER *) pAce;
  651. if (!AddAce(pDest, ACL_REVISION, 0xffffffff, pAce, aceHeader->AceSize))
  652. return HRESULT_FROM_WIN32(GetLastError());
  653. }
  654. return S_OK;
  655. }
  656. HRESULT CSecurityDescriptor::AddAccessDeniedACEToACL(PACL *ppAcl, LPCTSTR pszPrincipal, DWORD dwAccessMask)
  657. {
  658. ACL_SIZE_INFORMATION aclSizeInfo;
  659. int aclSize;
  660. DWORD returnValue;
  661. PSID principalSID;
  662. PACL oldACL, newACL;
  663. oldACL = *ppAcl;
  664. returnValue = GetPrincipalSID(pszPrincipal, &principalSID);
  665. if (FAILED(returnValue))
  666. return returnValue;
  667. aclSizeInfo.AclBytesInUse = 0;
  668. if (*ppAcl != NULL)
  669. GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
  670. aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_DENIED_ACE) + GetLengthSid(principalSID) - sizeof(DWORD);
  671. newACL = (PACL) new BYTE[aclSize];
  672. if (NULL==newACL)
  673. {
  674. delete[] (LPBYTE)principalSID;
  675. return E_OUTOFMEMORY;
  676. }
  677. if (!InitializeAcl(newACL, aclSize, ACL_REVISION))
  678. {
  679. delete[] (LPBYTE)(newACL);
  680. delete[] (LPBYTE)(principalSID);
  681. return HRESULT_FROM_WIN32(GetLastError());
  682. }
  683. if (!AddAccessDeniedAce(newACL, ACL_REVISION2, dwAccessMask, principalSID))
  684. {
  685. delete[] (LPBYTE)(newACL);
  686. delete[] (LPBYTE)(principalSID);
  687. return HRESULT_FROM_WIN32(GetLastError());
  688. }
  689. returnValue = CopyACL(newACL, oldACL);
  690. if (FAILED(returnValue))
  691. {
  692. delete[] (LPBYTE)(newACL);
  693. delete[] (LPBYTE)(principalSID);
  694. return returnValue;
  695. }
  696. *ppAcl = newACL;
  697. if (oldACL != NULL)
  698. delete[] (LPBYTE)(oldACL);
  699. delete[] (LPBYTE)(principalSID);
  700. return S_OK;
  701. }
  702. HRESULT CSecurityDescriptor::AddAccessDeniedACEToACL(PACL *ppAcl, const SecurityId *psidPrincipal, DWORD dwAccessMask)
  703. {
  704. ACL_SIZE_INFORMATION aclSizeInfo;
  705. int aclSize;
  706. DWORD returnValue;
  707. PSID principalSID;
  708. PACL oldACL, newACL;
  709. DWORD dwLen, dwIx;
  710. oldACL = *ppAcl;
  711. ASSERT(255 >= psidPrincipal->dwRidCount);
  712. dwLen = GetSidLengthRequired((UCHAR)psidPrincipal->dwRidCount);
  713. principalSID = (PSID)(new BYTE[dwLen]);
  714. if (NULL==principalSID)
  715. return E_OUTOFMEMORY;
  716. if (!InitializeSid(
  717. principalSID,
  718. (PSID_IDENTIFIER_AUTHORITY)&psidPrincipal->sid,
  719. (UCHAR)psidPrincipal->dwRidCount))
  720. {
  721. delete[] (LPBYTE)principalSID;
  722. return HRESULT_FROM_WIN32(GetLastError());
  723. }
  724. for (dwIx = 0; dwIx < psidPrincipal->dwRidCount; dwIx += 1)
  725. *GetSidSubAuthority(principalSID, dwIx) = psidPrincipal->rgRids[dwIx];
  726. if (!IsValidSid(principalSID))
  727. {
  728. delete[] (LPBYTE)principalSID;
  729. return HRESULT_FROM_WIN32(GetLastError());
  730. }
  731. aclSizeInfo.AclBytesInUse = 0;
  732. if (*ppAcl != NULL)
  733. GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
  734. aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_DENIED_ACE) + GetLengthSid(principalSID) - sizeof(DWORD);
  735. newACL = (PACL) new BYTE[aclSize];
  736. if (NULL==newACL)
  737. {
  738. delete[] (LPBYTE)principalSID;
  739. return E_OUTOFMEMORY;
  740. }
  741. if (!InitializeAcl(newACL, aclSize, ACL_REVISION))
  742. {
  743. delete[] (LPBYTE)newACL;
  744. delete[] (LPBYTE)(principalSID);
  745. return HRESULT_FROM_WIN32(GetLastError());
  746. }
  747. if (!AddAccessDeniedAce(newACL, ACL_REVISION2, dwAccessMask, principalSID))
  748. {
  749. delete[] (LPBYTE)newACL;
  750. delete[] (LPBYTE)(principalSID);
  751. return HRESULT_FROM_WIN32(GetLastError());
  752. }
  753. returnValue = CopyACL(newACL, oldACL);
  754. if (FAILED(returnValue))
  755. {
  756. delete[] (LPBYTE)newACL;
  757. delete[] (LPBYTE)(principalSID);
  758. return returnValue;
  759. }
  760. *ppAcl = newACL;
  761. if (oldACL != NULL)
  762. delete[] (LPBYTE)(oldACL);
  763. delete[] (LPBYTE)(principalSID);
  764. return S_OK;
  765. }
  766. HRESULT CSecurityDescriptor::AddAccessAllowedACEToACL(PACL *ppAcl, const SecurityId *psidPrincipal, DWORD dwAccessMask)
  767. {
  768. ACL_SIZE_INFORMATION aclSizeInfo;
  769. int aclSize;
  770. DWORD returnValue;
  771. PSID principalSID = NULL;
  772. PACL oldACL, newACL;
  773. DWORD dwLen, dwIx;
  774. oldACL = *ppAcl;
  775. ASSERT(255 >= psidPrincipal->dwRidCount);
  776. dwLen = GetSidLengthRequired((UCHAR)psidPrincipal->dwRidCount);
  777. principalSID = (PSID)(new BYTE[dwLen]);
  778. if (NULL==principalSID)
  779. return E_OUTOFMEMORY;
  780. if (!InitializeSid(
  781. principalSID,
  782. (PSID_IDENTIFIER_AUTHORITY)&psidPrincipal->sid,
  783. (UCHAR)psidPrincipal->dwRidCount))
  784. {
  785. delete[] (LPBYTE)principalSID;
  786. return HRESULT_FROM_WIN32(GetLastError());
  787. }
  788. for (dwIx = 0; dwIx < psidPrincipal->dwRidCount; dwIx += 1)
  789. *GetSidSubAuthority(principalSID, dwIx) = psidPrincipal->rgRids[dwIx];
  790. if (!IsValidSid(principalSID))
  791. {
  792. delete[] (LPBYTE)principalSID;
  793. return HRESULT_FROM_WIN32(GetLastError());
  794. }
  795. aclSizeInfo.AclBytesInUse = 0;
  796. if (*ppAcl != NULL)
  797. GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
  798. aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(principalSID) - sizeof(DWORD);
  799. newACL = (PACL) new BYTE[aclSize];
  800. if (NULL==newACL) {
  801. delete[] (LPBYTE)principalSID;
  802. return E_OUTOFMEMORY;
  803. }
  804. if (!InitializeAcl(newACL, aclSize, ACL_REVISION))
  805. {
  806. delete[] (LPBYTE)newACL;
  807. delete[] (LPBYTE)principalSID;
  808. return HRESULT_FROM_WIN32(GetLastError());
  809. }
  810. returnValue = CopyACL(newACL, oldACL);
  811. if (FAILED(returnValue))
  812. {
  813. delete[] (LPBYTE)newACL;
  814. delete[] (LPBYTE)principalSID;
  815. return returnValue;
  816. }
  817. if (!AddAccessAllowedAce(newACL, ACL_REVISION2, dwAccessMask, principalSID))
  818. {
  819. delete[] (LPBYTE)newACL;
  820. delete[] (LPBYTE)principalSID;
  821. return HRESULT_FROM_WIN32(GetLastError());
  822. }
  823. *ppAcl = newACL;
  824. if (oldACL != NULL)
  825. delete[] (LPBYTE)(oldACL);
  826. delete[] (LPBYTE)principalSID;
  827. return S_OK;
  828. }
  829. HRESULT CSecurityDescriptor::AddAccessAllowedACEToACL(PACL *ppAcl, LPCTSTR pszPrincipal, DWORD dwAccessMask)
  830. {
  831. ACL_SIZE_INFORMATION aclSizeInfo;
  832. int aclSize;
  833. DWORD returnValue;
  834. PSID principalSID;
  835. PACL oldACL, newACL;
  836. oldACL = *ppAcl;
  837. returnValue = GetPrincipalSID(pszPrincipal, &principalSID);
  838. if (FAILED(returnValue))
  839. return returnValue;
  840. aclSizeInfo.AclBytesInUse = 0;
  841. if (*ppAcl != NULL)
  842. GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
  843. aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(principalSID) - sizeof(DWORD);
  844. newACL = (PACL) new BYTE[aclSize];
  845. if (NULL==newACL)
  846. {
  847. delete[] (LPBYTE)principalSID;
  848. return E_OUTOFMEMORY;
  849. }
  850. if (!InitializeAcl(newACL, aclSize, ACL_REVISION))
  851. {
  852. delete[] (LPBYTE)(newACL);
  853. delete[] (LPBYTE)(principalSID);
  854. return HRESULT_FROM_WIN32(GetLastError());
  855. }
  856. returnValue = CopyACL(newACL, oldACL);
  857. if (FAILED(returnValue))
  858. {
  859. delete[] (LPBYTE)(newACL);
  860. delete[] (LPBYTE)(principalSID);
  861. return returnValue;
  862. }
  863. if (!AddAccessAllowedAce(newACL, ACL_REVISION2, dwAccessMask, principalSID))
  864. {
  865. delete[] (LPBYTE)(newACL);
  866. delete[] (LPBYTE)(principalSID);
  867. return HRESULT_FROM_WIN32(GetLastError());
  868. }
  869. *ppAcl = newACL;
  870. if (oldACL != NULL)
  871. delete[] (LPBYTE)(oldACL);
  872. delete[] (LPBYTE)(principalSID);
  873. return S_OK;
  874. }
  875. HRESULT CSecurityDescriptor::AddAccessAllowedACEToACL(PACL *ppAcl, DWORD dwAccessMask)
  876. {
  877. ACL_SIZE_INFORMATION aclSizeInfo;
  878. int aclSize;
  879. DWORD returnValue;
  880. PACL oldACL, newACL;
  881. oldACL = *ppAcl;
  882. if (!IsValidSid(m_pOwner))
  883. {
  884. _ASSERTE(FALSE);
  885. return E_INVALIDARG;
  886. }
  887. aclSizeInfo.AclBytesInUse = 0;
  888. if (*ppAcl != NULL)
  889. GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
  890. aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(m_pOwner) - sizeof(DWORD);
  891. newACL = (PACL) new BYTE[aclSize];
  892. if (NULL==newACL)
  893. {
  894. return E_OUTOFMEMORY;
  895. }
  896. if (!InitializeAcl(newACL, aclSize, ACL_REVISION))
  897. {
  898. delete[] (LPBYTE)(newACL);
  899. return HRESULT_FROM_WIN32(GetLastError());
  900. }
  901. returnValue = CopyACL(newACL, oldACL);
  902. if (FAILED(returnValue))
  903. {
  904. delete[] (LPBYTE)(newACL);
  905. return returnValue;
  906. }
  907. if (!AddAccessAllowedAce(newACL, ACL_REVISION2, dwAccessMask, m_pOwner))
  908. {
  909. delete[] (LPBYTE)(newACL);
  910. return HRESULT_FROM_WIN32(GetLastError());
  911. }
  912. *ppAcl = newACL;
  913. if (oldACL != NULL)
  914. delete[] (LPBYTE)(oldACL);
  915. return S_OK;
  916. }
  917. HRESULT CSecurityDescriptor::RemovePrincipalFromACL(PACL pAcl, LPCTSTR pszPrincipal)
  918. {
  919. ACL_SIZE_INFORMATION aclSizeInfo;
  920. ULONG i;
  921. LPVOID ace;
  922. ACCESS_ALLOWED_ACE *accessAllowedAce;
  923. ACCESS_DENIED_ACE *accessDeniedAce;
  924. SYSTEM_AUDIT_ACE *systemAuditAce;
  925. PSID principalSID;
  926. DWORD returnValue;
  927. ACE_HEADER *aceHeader;
  928. returnValue = GetPrincipalSID(pszPrincipal, &principalSID);
  929. if (FAILED(returnValue))
  930. return returnValue;
  931. GetAclInformation(pAcl, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
  932. for (i = 0; i < aclSizeInfo.AceCount; i++)
  933. {
  934. if (!GetAce(pAcl, i, &ace))
  935. {
  936. delete[] (LPBYTE)(principalSID);
  937. return HRESULT_FROM_WIN32(GetLastError());
  938. }
  939. aceHeader = (ACE_HEADER *) ace;
  940. if (aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
  941. {
  942. accessAllowedAce = (ACCESS_ALLOWED_ACE *) ace;
  943. if (EqualSid(principalSID, (PSID) &accessAllowedAce->SidStart))
  944. {
  945. DeleteAce(pAcl, i);
  946. delete[] (LPBYTE)(principalSID);
  947. return S_OK;
  948. }
  949. } else
  950. if (aceHeader->AceType == ACCESS_DENIED_ACE_TYPE)
  951. {
  952. accessDeniedAce = (ACCESS_DENIED_ACE *) ace;
  953. if (EqualSid(principalSID, (PSID) &accessDeniedAce->SidStart))
  954. {
  955. DeleteAce(pAcl, i);
  956. delete[] (LPBYTE)(principalSID);
  957. return S_OK;
  958. }
  959. } else
  960. if (aceHeader->AceType == SYSTEM_AUDIT_ACE_TYPE)
  961. {
  962. systemAuditAce = (SYSTEM_AUDIT_ACE *) ace;
  963. if (EqualSid(principalSID, (PSID) &systemAuditAce->SidStart))
  964. {
  965. DeleteAce(pAcl, i);
  966. delete[] (LPBYTE)(principalSID);
  967. return S_OK;
  968. }
  969. }
  970. }
  971. delete[] (LPBYTE)(principalSID);
  972. return S_OK;
  973. }
  974. HRESULT CSecurityDescriptor::SetPrivilege(LPCTSTR privilege, BOOL bEnable, HANDLE hToken)
  975. {
  976. HRESULT hr;
  977. TOKEN_PRIVILEGES tpPrevious;
  978. TOKEN_PRIVILEGES tp;
  979. DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES);
  980. LUID luid;
  981. HANDLE hMyToken = NULL;
  982. // if no token specified open process token
  983. if (hToken == 0)
  984. {
  985. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hMyToken))
  986. {
  987. hr = HRESULT_FROM_WIN32(GetLastError());
  988. _ASSERTE(FALSE);
  989. return hr;
  990. }
  991. hToken = hMyToken;
  992. }
  993. if (!LookupPrivilegeValue(NULL, privilege, &luid ))
  994. {
  995. hr = HRESULT_FROM_WIN32(GetLastError());
  996. _ASSERTE(FALSE);
  997. if (NULL != hMyToken)
  998. CloseHandle(hMyToken);
  999. return hr;
  1000. }
  1001. tp.PrivilegeCount = 1;
  1002. tp.Privileges[0].Luid = luid;
  1003. tp.Privileges[0].Attributes = 0;
  1004. if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious))
  1005. {
  1006. hr = HRESULT_FROM_WIN32(GetLastError());
  1007. _ASSERTE(FALSE);
  1008. if (NULL != hMyToken)
  1009. CloseHandle(hMyToken);
  1010. return hr;
  1011. }
  1012. tpPrevious.PrivilegeCount = 1;
  1013. tpPrevious.Privileges[0].Luid = luid;
  1014. if (bEnable)
  1015. tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
  1016. else
  1017. tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes);
  1018. if (!AdjustTokenPrivileges(hToken, FALSE, &tpPrevious, cbPrevious, NULL, NULL))
  1019. {
  1020. hr = HRESULT_FROM_WIN32(GetLastError());
  1021. _ASSERTE(FALSE);
  1022. if (NULL != hMyToken)
  1023. CloseHandle(hMyToken);
  1024. return hr;
  1025. }
  1026. if (NULL != hMyToken)
  1027. CloseHandle(hMyToken);
  1028. return S_OK;
  1029. }
  1030. CSecurityDescriptor::operator LPSECURITY_ATTRIBUTES()
  1031. {
  1032. m_saAttrs.nLength = sizeof (m_saAttrs);
  1033. m_saAttrs.lpSecurityDescriptor = m_pSD;
  1034. m_saAttrs.bInheritHandle = m_fInheritance;
  1035. return (&m_saAttrs);
  1036. }