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.

2368 lines
71 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. Security.cpp
  5. Abstract:
  6. This file contains the implementation of various security functions/classes.
  7. Revision History:
  8. Davide Massarenti (Dmassare) 04/26/2000
  9. created
  10. ******************************************************************************/
  11. #include "stdafx.h"
  12. ////////////////////////////////////////////////////////////////////////////////
  13. ////////////////////////////////////////////////////////////////////////////////
  14. ////////////////////////////////////////////////////////////////////////////////
  15. const SID MPC::SecurityDescriptor::s_EveryoneSid = { SID_REVISION, 1, SECURITY_WORLD_SID_AUTHORITY, SECURITY_WORLD_RID };
  16. const SID MPC::SecurityDescriptor::s_SystemSid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY , SECURITY_LOCAL_SYSTEM_RID };
  17. const MPC::SID2 MPC::SecurityDescriptor::s_AdminSid =
  18. {
  19. SID_REVISION ,
  20. 2 ,
  21. SECURITY_NT_AUTHORITY ,
  22. SECURITY_BUILTIN_DOMAIN_RID,
  23. DOMAIN_USER_RID_ADMIN
  24. };
  25. const MPC::SID2 MPC::SecurityDescriptor::s_Alias_AdminsSid =
  26. {
  27. SID_REVISION ,
  28. 2 ,
  29. SECURITY_NT_AUTHORITY ,
  30. SECURITY_BUILTIN_DOMAIN_RID,
  31. DOMAIN_ALIAS_RID_ADMINS
  32. };
  33. const MPC::SID2 MPC::SecurityDescriptor::s_Alias_PowerUsersSid =
  34. {
  35. SID_REVISION ,
  36. 2 ,
  37. SECURITY_NT_AUTHORITY ,
  38. SECURITY_BUILTIN_DOMAIN_RID,
  39. DOMAIN_ALIAS_RID_POWER_USERS
  40. };
  41. const MPC::SID2 MPC::SecurityDescriptor::s_Alias_UsersSid =
  42. {
  43. SID_REVISION ,
  44. 2 ,
  45. SECURITY_NT_AUTHORITY ,
  46. SECURITY_BUILTIN_DOMAIN_RID,
  47. DOMAIN_ALIAS_RID_USERS
  48. };
  49. const MPC::SID2 MPC::SecurityDescriptor::s_Alias_GuestsSid =
  50. {
  51. SID_REVISION ,
  52. 2 ,
  53. SECURITY_NT_AUTHORITY ,
  54. SECURITY_BUILTIN_DOMAIN_RID,
  55. DOMAIN_ALIAS_RID_GUESTS
  56. };
  57. ////////////////////////////////////////////////////////////////////////////////
  58. static DWORD Local_GenerateAccessMask( /*[in]*/ SECURITY_INFORMATION secInfo, /*[in]*/ bool fRead )
  59. {
  60. DWORD dwAccess;
  61. if(fRead)
  62. {
  63. dwAccess = 0;
  64. if(secInfo & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION))
  65. {
  66. dwAccess |= READ_CONTROL;
  67. }
  68. if(secInfo & SACL_SECURITY_INFORMATION)
  69. {
  70. dwAccess |= ACCESS_SYSTEM_SECURITY;
  71. }
  72. }
  73. else
  74. {
  75. dwAccess = MAXIMUM_ALLOWED;
  76. if(secInfo & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
  77. {
  78. dwAccess |= WRITE_OWNER;
  79. }
  80. if(secInfo & DACL_SECURITY_INFORMATION)
  81. {
  82. dwAccess |= WRITE_DAC;
  83. }
  84. if(secInfo & SACL_SECURITY_INFORMATION)
  85. {
  86. dwAccess |= ACCESS_SYSTEM_SECURITY;
  87. }
  88. }
  89. return dwAccess;
  90. }
  91. ////////////////////////////////////////////////////////////////////////////////
  92. ////////////////////////////////////////////////////////////////////////////////
  93. ////////////////////////////////////////////////////////////////////////////////
  94. HRESULT MPC::SecurityDescriptor::AllocateMemory( /*[in/out]*/ LPVOID& ptr ,
  95. /*[in] */ size_t iLen )
  96. {
  97. ReleaseMemory( ptr );
  98. ATLTRY(ptr = malloc( iLen ));
  99. return (ptr == NULL) ? E_OUTOFMEMORY : S_OK;
  100. }
  101. void MPC::SecurityDescriptor::ReleaseMemory( /*[in/out]*/ LPVOID& ptr )
  102. {
  103. if(ptr)
  104. {
  105. free( ptr ); ptr = NULL;
  106. }
  107. }
  108. void MPC::SecurityDescriptor::InitLsaString( /*[in/out]*/ LSA_UNICODE_STRING& lsaString ,
  109. /*[in ]*/ LPCWSTR szText )
  110. {
  111. if(szText == NULL)
  112. {
  113. lsaString.Buffer = NULL;
  114. lsaString.Length = 0;
  115. lsaString.MaximumLength = 0;
  116. }
  117. else
  118. {
  119. DWORD dwLen = wcslen( szText );
  120. lsaString.Buffer = (LPWSTR) szText;
  121. lsaString.Length = dwLen * sizeof(WCHAR);
  122. lsaString.MaximumLength = (dwLen+1) * sizeof(WCHAR);
  123. }
  124. }
  125. ////////////////////////////////////////////////////////////////////////////////
  126. ////////////////////////////////////////////////////////////////////////////////
  127. ////////////////////////////////////////////////////////////////////////////////
  128. HRESULT MPC::SecurityDescriptor::SetPrivilege( /*[in]*/ LPCWSTR Privilege ,
  129. /*[in]*/ BOOL bEnable ,
  130. /*[in]*/ HANDLE hToken )
  131. {
  132. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::SetPrivilege" );
  133. HRESULT hr;
  134. TOKEN_PRIVILEGES tp;
  135. TOKEN_PRIVILEGES tpPrevious;
  136. DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES);
  137. LUID luid;
  138. HANDLE hTokenUsed = NULL;
  139. // if no token specified open process token
  140. if(hToken == NULL)
  141. {
  142. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::OpenProcessToken( ::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hTokenUsed ));
  143. hToken = hTokenUsed;
  144. }
  145. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::LookupPrivilegeValueW( NULL, Privilege, &luid ));
  146. tp.PrivilegeCount = 1;
  147. tp.Privileges[0].Luid = luid;
  148. tp.Privileges[0].Attributes = 0;
  149. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious ));
  150. tpPrevious.PrivilegeCount = 1;
  151. tpPrevious.Privileges[0].Luid = luid;
  152. if(bEnable) tpPrevious.Privileges[0].Attributes |= SE_PRIVILEGE_ENABLED;
  153. else tpPrevious.Privileges[0].Attributes &= ~SE_PRIVILEGE_ENABLED;
  154. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::AdjustTokenPrivileges( hToken, FALSE, &tpPrevious, cbPrevious, NULL, NULL ));
  155. hr = S_OK;
  156. __MPC_FUNC_CLEANUP;
  157. if(hTokenUsed) ::CloseHandle( hTokenUsed );
  158. __MPC_FUNC_EXIT(hr);
  159. }
  160. HRESULT MPC::SecurityDescriptor::AddPrivilege( /*[in]*/ LPCWSTR szPrincipal ,
  161. /*[in]*/ LPCWSTR szPrivilege )
  162. {
  163. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::AddPrivilege" );
  164. HRESULT hr;
  165. NTSTATUS ntRes;
  166. LSA_OBJECT_ATTRIBUTES objectAttributes; ::ZeroMemory( &objectAttributes, sizeof(objectAttributes) );
  167. LSA_UNICODE_STRING lsaPrivilege;
  168. PSID pSid = NULL;
  169. HANDLE policyHandle = NULL;
  170. InitLsaString( lsaPrivilege, szPrivilege );
  171. __MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( szPrincipal, pSid ));
  172. ntRes = ::LsaOpenPolicy( NULL, &objectAttributes, POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, &policyHandle );
  173. if(ntRes != STATUS_SUCCESS)
  174. {
  175. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ::LsaNtStatusToWinError( ntRes ));
  176. }
  177. ntRes = ::LsaAddAccountRights( policyHandle, pSid, &lsaPrivilege, 1 );
  178. if(ntRes != STATUS_SUCCESS)
  179. {
  180. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ::LsaNtStatusToWinError( ntRes ));
  181. }
  182. hr = S_OK;
  183. __MPC_FUNC_CLEANUP;
  184. ReleaseMemory( (void*&)pSid );
  185. if(policyHandle) ::LsaClose( policyHandle );
  186. __MPC_FUNC_EXIT(hr);
  187. }
  188. HRESULT MPC::SecurityDescriptor::RemovePrivilege( /*[in]*/ LPCWSTR szPrincipal ,
  189. /*[in]*/ LPCWSTR szPrivilege )
  190. {
  191. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::RemovePrivilege" );
  192. HRESULT hr;
  193. NTSTATUS ntRes;
  194. LSA_OBJECT_ATTRIBUTES objectAttributes; ::ZeroMemory( &objectAttributes, sizeof(objectAttributes) );
  195. LSA_UNICODE_STRING lsaPrivilege;
  196. PSID pSid = NULL;
  197. HANDLE policyHandle = NULL;
  198. InitLsaString( lsaPrivilege, szPrivilege );
  199. __MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( szPrincipal, pSid ));
  200. ntRes = ::LsaOpenPolicy( NULL, &objectAttributes, POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, &policyHandle );
  201. if(ntRes != STATUS_SUCCESS)
  202. {
  203. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ::LsaNtStatusToWinError( ntRes ));
  204. }
  205. ntRes = ::LsaRemoveAccountRights( policyHandle, pSid, FALSE, &lsaPrivilege, 1 );
  206. if(ntRes != STATUS_SUCCESS)
  207. {
  208. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ::LsaNtStatusToWinError( ntRes ));
  209. }
  210. hr = S_OK;
  211. __MPC_FUNC_CLEANUP;
  212. ReleaseMemory( (void*&)pSid );
  213. if(policyHandle) ::LsaClose( policyHandle );
  214. __MPC_FUNC_EXIT(hr);
  215. }
  216. ////////////////////////////////////////////////////////////////////////////////
  217. HRESULT MPC::SecurityDescriptor::GetTokenSids( /*[in] */ HANDLE hToken ,
  218. /*[out]*/ PSID *ppUserSid ,
  219. /*[out]*/ PSID *ppGroupSid )
  220. {
  221. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::GetTokenSids" );
  222. HRESULT hr;
  223. DWORD dwRes;
  224. PTOKEN_USER ptkUser = NULL;
  225. PTOKEN_PRIMARY_GROUP ptkGroup = NULL;
  226. PSID pSid = NULL;
  227. DWORD dwSize = 0;
  228. if(ppUserSid ) *ppUserSid = NULL;
  229. if(ppGroupSid) *ppGroupSid = NULL;
  230. if(ppUserSid)
  231. {
  232. // Get length required for TokenUser by specifying buffer length of 0
  233. ::GetTokenInformation( hToken, TokenUser, NULL, 0, &dwSize );
  234. if((dwRes = ::GetLastError()) != ERROR_INSUFFICIENT_BUFFER)
  235. {
  236. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes);
  237. }
  238. __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)ptkUser, dwSize ));
  239. // Get Sid of process token.
  240. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetTokenInformation( hToken, TokenUser, ptkUser, dwSize, &dwSize ));
  241. // Make a copy of the Sid for the return value
  242. dwSize = ::GetLengthSid( ptkUser->User.Sid );
  243. __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( pSid, dwSize ));
  244. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CopySid( dwSize, pSid, ptkUser->User.Sid ));
  245. ATLASSERT(::IsValidSid( pSid ));
  246. *ppUserSid = pSid; pSid = NULL;
  247. }
  248. if(ppGroupSid)
  249. {
  250. // Get length required for TokenPrimaryGroup by specifying buffer length of 0
  251. ::GetTokenInformation( hToken, TokenPrimaryGroup, NULL, 0, &dwSize );
  252. if((dwRes = ::GetLastError()) != ERROR_INSUFFICIENT_BUFFER)
  253. {
  254. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes);
  255. }
  256. __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)ptkGroup, dwSize ));
  257. // Get Sid of process token.
  258. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetTokenInformation( hToken, TokenPrimaryGroup, ptkGroup, dwSize, &dwSize ));
  259. // Make a copy of the Sid for the return value
  260. dwSize = ::GetLengthSid( ptkGroup->PrimaryGroup );
  261. __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( pSid, dwSize ));
  262. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CopySid( dwSize, pSid, ptkGroup->PrimaryGroup ));
  263. ATLASSERT(::IsValidSid( pSid ));
  264. *ppGroupSid = pSid; pSid = NULL;
  265. }
  266. hr = S_OK;
  267. __MPC_FUNC_CLEANUP;
  268. ReleaseMemory( (void*&)ptkUser );
  269. ReleaseMemory( (void*&)ptkGroup );
  270. ReleaseMemory( (void*&)pSid );
  271. __MPC_FUNC_EXIT(hr);
  272. }
  273. HRESULT MPC::SecurityDescriptor::GetProcessSids( /*[out]*/ PSID *ppUserSid ,
  274. /*[out]*/ PSID *ppGroupSid )
  275. {
  276. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::GetProcessSids" );
  277. HRESULT hr;
  278. HANDLE hToken = NULL;
  279. if(ppUserSid ) *ppUserSid = NULL;
  280. if(ppGroupSid) *ppGroupSid = NULL;
  281. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::OpenProcessToken( ::GetCurrentProcess(), TOKEN_QUERY, &hToken ));
  282. __MPC_EXIT_IF_METHOD_FAILS(hr, GetTokenSids( hToken, ppUserSid, ppGroupSid ));
  283. hr = S_OK;
  284. __MPC_FUNC_CLEANUP;
  285. if(hToken) ::CloseHandle( hToken );
  286. __MPC_FUNC_EXIT(hr);
  287. }
  288. HRESULT MPC::SecurityDescriptor::GetThreadSids( /*[out]*/ PSID *ppUserSid ,
  289. /*[out]*/ PSID *ppGroupSid ,
  290. /*[in] */ BOOL bOpenAsSelf )
  291. {
  292. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::GetThreadSids" );
  293. HRESULT hr;
  294. HANDLE hToken = NULL;
  295. if(ppUserSid ) *ppUserSid = NULL;
  296. if(ppGroupSid) *ppGroupSid = NULL;
  297. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::OpenThreadToken( ::GetCurrentThread(), TOKEN_QUERY, bOpenAsSelf, &hToken ));
  298. __MPC_EXIT_IF_METHOD_FAILS(hr, GetTokenSids( hToken, ppUserSid, ppGroupSid ));
  299. hr = S_OK;
  300. __MPC_FUNC_CLEANUP;
  301. if(hToken) ::CloseHandle( hToken );
  302. __MPC_FUNC_EXIT(hr);
  303. }
  304. ////////////////////////////////////////////////////////////////////////////////
  305. ////////////////////////////////////////////////////////////////////////////////
  306. ////////////////////////////////////////////////////////////////////////////////
  307. HRESULT MPC::SecurityDescriptor::VerifyPrincipal( /*[in]*/ LPCWSTR szPrincipal )
  308. {
  309. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::VerifyPrincipal" );
  310. HRESULT hr;
  311. PSID pSid = NULL;
  312. __MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( szPrincipal, pSid ));
  313. hr = S_OK;
  314. __MPC_FUNC_CLEANUP;
  315. ReleaseMemory( (void*&)pSid );
  316. __MPC_FUNC_EXIT(hr);
  317. }
  318. HRESULT MPC::SecurityDescriptor::ConvertPrincipalToSID( /*[in ]*/ LPCWSTR szPrincipal ,
  319. /*[out]*/ PSID& pSid ,
  320. /*[out]*/ LPCWSTR *pszDomain )
  321. {
  322. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::ConvertPrincipalToSID" );
  323. HRESULT hr;
  324. DWORD dwRes;
  325. LPWSTR szDomain = NULL;
  326. DWORD dwDomainSize = 0;
  327. DWORD dwSidSize = 0;
  328. PSID pSidLocal = NULL;
  329. SID_NAME_USE snu;
  330. if(pszDomain) *pszDomain = NULL;
  331. if(::ConvertStringSidToSidW( szPrincipal, &pSidLocal ))
  332. {
  333. dwSidSize = ::GetLengthSid( pSidLocal );
  334. __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)pSid, dwSidSize ));
  335. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CopySid( dwSidSize, pSid, pSidLocal ));
  336. }
  337. else
  338. {
  339. //
  340. // Call to get size info for alloc
  341. //
  342. ::LookupAccountNameW( NULL, szPrincipal, NULL, &dwSidSize, NULL, &dwDomainSize, &snu );
  343. if((dwRes = ::GetLastError()) != ERROR_INSUFFICIENT_BUFFER)
  344. {
  345. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes);
  346. }
  347. __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)pSid , dwSidSize ));
  348. __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)szDomain, sizeof(WCHAR)*(dwDomainSize+1) ));
  349. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::LookupAccountNameW( NULL, szPrincipal, pSid, &dwSidSize, szDomain, &dwDomainSize, &snu ));
  350. if(pszDomain) { *pszDomain = szDomain; szDomain = NULL; }
  351. }
  352. hr = S_OK;
  353. __MPC_FUNC_CLEANUP;
  354. if(pSidLocal) ::LocalFree( pSidLocal );
  355. ReleaseMemory( (void*&)szDomain );
  356. __MPC_FUNC_EXIT(hr);
  357. }
  358. HRESULT MPC::SecurityDescriptor::ConvertSIDToPrincipal( /*[in] */ PSID pSid ,
  359. /*[out]*/ LPCWSTR *pszPrincipal ,
  360. /*[out]*/ LPCWSTR *pszDomain )
  361. {
  362. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::ConvertSIDToPrincipal" );
  363. HRESULT hr;
  364. DWORD dwRes;
  365. LPWSTR szPrincipal = NULL;
  366. LPWSTR szDomain = NULL;
  367. DWORD dwPrincipalSize = 0;
  368. DWORD dwDomainSize = 0;
  369. SID_NAME_USE snu;
  370. if(pszPrincipal) *pszPrincipal = NULL;
  371. if(pszDomain ) *pszDomain = NULL;
  372. // Call to get size info for alloc
  373. ::LookupAccountSidW( NULL, pSid, NULL, &dwPrincipalSize, NULL, &dwDomainSize, &snu );
  374. if((dwRes = ::GetLastError()) != ERROR_INSUFFICIENT_BUFFER)
  375. {
  376. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes);
  377. }
  378. __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)szPrincipal, sizeof(WCHAR)*(dwPrincipalSize+1) ));
  379. __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)szDomain , sizeof(WCHAR)*(dwDomainSize +1) ));
  380. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::LookupAccountSidW( NULL, pSid, szPrincipal, &dwPrincipalSize, szDomain, &dwDomainSize, &snu ));
  381. if(pszDomain == NULL && szDomain[0])
  382. {
  383. if(pszPrincipal)
  384. {
  385. LPWSTR szPrincipalAndDomain = NULL;
  386. UINT cchAlloc = dwPrincipalSize+dwDomainSize+2;
  387. __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)szPrincipalAndDomain, cchAlloc*sizeof(WCHAR)));
  388. StringCchCopyW( szPrincipalAndDomain, cchAlloc, szDomain );
  389. StringCchCatW( szPrincipalAndDomain, cchAlloc, L"\\" );
  390. StringCchCatW( szPrincipalAndDomain, cchAlloc, szPrincipal );
  391. *pszPrincipal = szPrincipalAndDomain;
  392. }
  393. }
  394. else
  395. {
  396. if(pszPrincipal) { *pszPrincipal = szPrincipal; szPrincipal = NULL; }
  397. if(pszDomain ) { *pszDomain = szDomain ; szDomain = NULL; }
  398. }
  399. hr = S_OK;
  400. __MPC_FUNC_CLEANUP;
  401. ReleaseMemory( (void*&)szPrincipal );
  402. ReleaseMemory( (void*&)szDomain );
  403. __MPC_FUNC_EXIT(hr);
  404. }
  405. HRESULT MPC::SecurityDescriptor::ConvertSIDToPrincipal( /*[in] */ PSID pSid ,
  406. /*[out]*/ MPC::wstring& strPrincipal )
  407. {
  408. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::ConvertSIDToPrincipal" );
  409. HRESULT hr;
  410. LPCWSTR szPrincipal = NULL;
  411. __MPC_EXIT_IF_METHOD_FAILS(hr, ConvertSIDToPrincipal( pSid, &szPrincipal ));
  412. strPrincipal = SAFEWSTR( szPrincipal );
  413. hr = S_OK;
  414. __MPC_FUNC_CLEANUP;
  415. ReleaseMemory( (void*&)szPrincipal );
  416. __MPC_FUNC_EXIT(hr);
  417. }
  418. HRESULT MPC::SecurityDescriptor::NormalizePrincipalToStringSID( /*[in ]*/ LPCWSTR szPrincipal ,
  419. /*[in ]*/ LPCWSTR szDomain ,
  420. /*[out]*/ MPC::wstring& strSID )
  421. {
  422. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::NormalizePrincipalToStringSID" );
  423. HRESULT hr;
  424. MPC::wstring strAccount;
  425. PSID pSid = NULL;
  426. LPWSTR szUserSid = NULL;
  427. if(szDomain)
  428. {
  429. strAccount = szDomain;
  430. strAccount += L"\\";
  431. }
  432. strAccount += SAFEWSTR(szPrincipal);
  433. //
  434. // First convert the principal to a SID, then back to a string.
  435. //
  436. __MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( strAccount.c_str(), pSid ));
  437. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::ConvertSidToStringSidW( pSid, &szUserSid ));
  438. strSID = SAFEWSTR( szUserSid );
  439. hr = S_OK;
  440. __MPC_FUNC_CLEANUP;
  441. if(szUserSid) ::LocalFree( szUserSid );
  442. ReleaseMemory( (void*&)pSid );
  443. __MPC_FUNC_EXIT(hr);
  444. }
  445. ////////////////////////////////////////////////////////////////////////////////
  446. ////////////////////////////////////////////////////////////////////////////////
  447. ////////////////////////////////////////////////////////////////////////////////
  448. HRESULT MPC::SecurityDescriptor::GetAccountName( /*[in]*/ LPCWSTR szPrincipal, /*[out]*/ MPC::wstring& strName )
  449. {
  450. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::GetAccountName" );
  451. HRESULT hr;
  452. PSID pSid = NULL;
  453. LPCWSTR szUser = NULL;
  454. LPCWSTR szDomain = NULL;
  455. __MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( szPrincipal, pSid ));
  456. __MPC_EXIT_IF_METHOD_FAILS(hr, ConvertSIDToPrincipal( pSid, &szUser, &szDomain ));
  457. strName = SAFEWSTR(szUser);
  458. hr = S_OK;
  459. __MPC_FUNC_CLEANUP;
  460. ReleaseMemory( (void*&)pSid );
  461. ReleaseMemory( (void*&)szUser );
  462. ReleaseMemory( (void*&)szDomain );
  463. __MPC_FUNC_EXIT(hr);
  464. }
  465. HRESULT MPC::SecurityDescriptor::GetAccountDomain( /*[in]*/ LPCWSTR szPrincipal, /*[out]*/ MPC::wstring& strName )
  466. {
  467. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::GetAccountDomain" );
  468. HRESULT hr;
  469. PSID pSid = NULL;
  470. LPCWSTR szUser = NULL;
  471. LPCWSTR szDomain = NULL;
  472. __MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( szPrincipal, pSid ));
  473. __MPC_EXIT_IF_METHOD_FAILS(hr, ConvertSIDToPrincipal( pSid, &szUser, &szDomain ));
  474. strName = SAFEWSTR(szDomain);
  475. hr = S_OK;
  476. __MPC_FUNC_CLEANUP;
  477. ReleaseMemory( (void*&)pSid );
  478. ReleaseMemory( (void*&)szUser );
  479. ReleaseMemory( (void*&)szDomain );
  480. __MPC_FUNC_EXIT(hr);
  481. }
  482. HRESULT MPC::SecurityDescriptor::GetAccountDisplayName( /*[in]*/ LPCWSTR szPrincipal, /*[out]*/ MPC::wstring& strName )
  483. {
  484. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::GetAccountDisplayName" );
  485. HRESULT hr;
  486. PSID pSid = NULL;
  487. LPCWSTR szUser = NULL;
  488. LPWSTR szDisplay = NULL;
  489. ULONG lSize = 0;
  490. __MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( szPrincipal, pSid ));
  491. __MPC_EXIT_IF_METHOD_FAILS(hr, ConvertSIDToPrincipal( pSid, &szUser ));
  492. //
  493. // First call is to get size, second to get the actual data.
  494. //
  495. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::TranslateNameW( szUser, NameSamCompatible, NameDisplay, NULL, &lSize ));
  496. __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)szDisplay, sizeof(WCHAR)*(lSize+1) ));
  497. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::TranslateNameW( szUser, NameSamCompatible, NameDisplay, szDisplay, &lSize ));
  498. strName = SAFEWSTR(szDisplay);
  499. hr = S_OK;
  500. __MPC_FUNC_CLEANUP;
  501. ReleaseMemory( (void*&)pSid );
  502. ReleaseMemory( (void*&)szUser );
  503. ReleaseMemory( (void*&)szDisplay );
  504. __MPC_FUNC_EXIT(hr);
  505. }
  506. ////////////////////////////////////////////////////////////////////////////////
  507. ////////////////////////////////////////////////////////////////////////////////
  508. ////////////////////////////////////////////////////////////////////////////////
  509. HRESULT MPC::SecurityDescriptor::CopyACL( /*[in]*/ PACL pDest,
  510. /*[in]*/ PACL pSrc )
  511. {
  512. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::CopyACL" );
  513. HRESULT hr;
  514. ACL_SIZE_INFORMATION aclSizeInfo;
  515. ACE_HEADER* aceHeader;
  516. LPVOID pACE;
  517. if(pSrc)
  518. {
  519. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetAclInformation( pSrc, (LPVOID)&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation ));
  520. // Copy all of the ACEs to the new ACL
  521. for(DWORD i = 0; i < aclSizeInfo.AceCount; i++)
  522. {
  523. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetAce( pSrc, i, (LPVOID*)&pACE ));
  524. aceHeader = (ACE_HEADER *)pACE;
  525. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::AddAce( pDest, ACL_REVISION, 0xFFFFFFFF, pACE, aceHeader->AceSize ));
  526. }
  527. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::IsValidAcl( pDest ));
  528. }
  529. hr = S_OK;
  530. __MPC_FUNC_CLEANUP;
  531. __MPC_FUNC_EXIT(hr);
  532. }
  533. HRESULT MPC::SecurityDescriptor::CloneACL( /*[in/out]*/ PACL& pDest ,
  534. /*[in ]*/ PACL pSrc )
  535. {
  536. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::CloneACL" );
  537. HRESULT hr;
  538. ACL_SIZE_INFORMATION aclSizeInfo;
  539. ReleaseMemory( (void*&)pDest );
  540. if(pSrc)
  541. {
  542. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetAclInformation( pSrc, (LPVOID)&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation ));
  543. __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)pDest, pSrc->AclSize ));
  544. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::InitializeAcl( pDest, pSrc->AclSize, ACL_REVISION ));
  545. __MPC_EXIT_IF_METHOD_FAILS(hr, CopyACL( pDest, pSrc ));
  546. }
  547. hr = S_OK;
  548. __MPC_FUNC_CLEANUP;
  549. __MPC_FUNC_EXIT(hr);
  550. }
  551. HRESULT MPC::SecurityDescriptor::EnsureACLSize( /*[in/out]*/ PACL& pACL ,
  552. /*[in ]*/ DWORD dwExpand )
  553. {
  554. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::EnsureACLSize" );
  555. HRESULT hr;
  556. DWORD dwSizeAvailable;
  557. DWORD dwSizeRequired;
  558. ACL_SIZE_INFORMATION aclSizeInfo;
  559. PACL newACL = NULL;
  560. if(pACL)
  561. {
  562. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetAclInformation( pACL, (LPVOID)&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation ));
  563. dwSizeAvailable = pACL->AclSize;
  564. dwSizeRequired = aclSizeInfo.AclBytesInUse + dwExpand;
  565. }
  566. else
  567. {
  568. ::ZeroMemory( &aclSizeInfo, sizeof(aclSizeInfo) );
  569. dwSizeAvailable = 0;
  570. dwSizeRequired = sizeof(ACL) + dwExpand;
  571. }
  572. //
  573. // If too little free space is
  574. //
  575. if(dwSizeAvailable < dwSizeRequired)
  576. {
  577. __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)newACL, dwSizeRequired ));
  578. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::InitializeAcl( newACL, dwSizeRequired, ACL_REVISION ));
  579. __MPC_EXIT_IF_METHOD_FAILS(hr, CopyACL( newACL, pACL ));
  580. ReleaseMemory( (void*&)pACL ); pACL = newACL; newACL = NULL;
  581. }
  582. hr = S_OK;
  583. __MPC_FUNC_CLEANUP;
  584. ReleaseMemory( (void*&)newACL );
  585. __MPC_FUNC_EXIT(hr);
  586. }
  587. ////////////////////////////////////////////////////////////////////////////////
  588. HRESULT MPC::SecurityDescriptor::RemovePrincipalFromACL( /*[in]*/ PACL pACL ,
  589. /*[in]*/ PSID pPrincipalSid ,
  590. /*[in]*/ int pos )
  591. {
  592. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::RemovePrincipalFromACL" );
  593. HRESULT hr;
  594. DWORD i;
  595. int seen = 0;
  596. ACL_SIZE_INFORMATION aclSizeInfo;
  597. PACE_HEADER aceHeader;
  598. PSID pSid;
  599. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetAclInformation( pACL, (LPVOID)&aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation ));
  600. for(i = 0; i < aclSizeInfo.AceCount; i++)
  601. {
  602. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetAce(pACL, i, (LPVOID*)&aceHeader));
  603. switch(aceHeader->AceType)
  604. {
  605. case ACCESS_ALLOWED_ACE_TYPE : pSid = &((PACCESS_ALLOWED_ACE )aceHeader)->SidStart; break;
  606. case ACCESS_ALLOWED_OBJECT_ACE_TYPE: pSid = &((PACCESS_ALLOWED_OBJECT_ACE)aceHeader)->SidStart; break;
  607. case ACCESS_DENIED_ACE_TYPE : pSid = &((PACCESS_DENIED_ACE )aceHeader)->SidStart; break;
  608. case ACCESS_DENIED_OBJECT_ACE_TYPE : pSid = &((PACCESS_DENIED_OBJECT_ACE )aceHeader)->SidStart; break;
  609. case SYSTEM_AUDIT_ACE_TYPE : pSid = &((PSYSTEM_AUDIT_ACE )aceHeader)->SidStart; break;
  610. case SYSTEM_AUDIT_OBJECT_ACE_TYPE : pSid = &((PSYSTEM_AUDIT_OBJECT_ACE )aceHeader)->SidStart; break;
  611. default : __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
  612. }
  613. if(::EqualSid( pPrincipalSid, pSid ))
  614. {
  615. if(seen == pos || pos == -1)
  616. {
  617. ::DeleteAce( pACL, i );
  618. aclSizeInfo.AceCount--;
  619. i--;
  620. }
  621. seen++;
  622. }
  623. }
  624. hr = S_OK;
  625. __MPC_FUNC_CLEANUP;
  626. __MPC_FUNC_EXIT(hr);
  627. }
  628. HRESULT MPC::SecurityDescriptor::AddACEToACL( /*[in/out]*/ PACL& pACL ,
  629. /*[in ]*/ PSID pPrincipalSid ,
  630. /*[in ]*/ DWORD dwAceType ,
  631. /*[in ]*/ DWORD dwAceFlags ,
  632. /*[in ]*/ DWORD dwAccessMask ,
  633. /*[in ]*/ GUID* guidObjectType ,
  634. /*[in ]*/ GUID* guidInheritedObjectType )
  635. {
  636. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::AddACEToACL" );
  637. HRESULT hr;
  638. DWORD dwSize;
  639. BOOL fRes;
  640. dwSize = ::GetLengthSid( pPrincipalSid );
  641. switch(dwAceType)
  642. {
  643. case ACCESS_ALLOWED_ACE_TYPE : dwSize += sizeof(ACCESS_ALLOWED_ACE ) - sizeof(DWORD); break;
  644. case ACCESS_ALLOWED_OBJECT_ACE_TYPE: dwSize += sizeof(ACCESS_ALLOWED_OBJECT_ACE) - sizeof(DWORD); break;
  645. case ACCESS_DENIED_ACE_TYPE : dwSize += sizeof(ACCESS_DENIED_ACE ) - sizeof(DWORD); break;
  646. case ACCESS_DENIED_OBJECT_ACE_TYPE : dwSize += sizeof(ACCESS_DENIED_OBJECT_ACE ) - sizeof(DWORD); break;
  647. case SYSTEM_AUDIT_ACE_TYPE : dwSize += sizeof(SYSTEM_AUDIT_ACE ) - sizeof(DWORD); break;
  648. case SYSTEM_AUDIT_OBJECT_ACE_TYPE : dwSize += sizeof(SYSTEM_AUDIT_OBJECT_ACE ) - sizeof(DWORD); break;
  649. default : __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
  650. }
  651. __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureACLSize( pACL, dwSize ));
  652. switch(dwAceType)
  653. {
  654. case ACCESS_ALLOWED_ACE_TYPE : fRes = ::AddAccessAllowedAceEx ( pACL, ACL_REVISION, dwAceFlags, dwAccessMask , pPrincipalSid ); break;
  655. case ACCESS_ALLOWED_OBJECT_ACE_TYPE: fRes = ::AddAccessAllowedObjectAce( pACL, ACL_REVISION, dwAceFlags, dwAccessMask, guidObjectType, guidInheritedObjectType, pPrincipalSid ); break;
  656. case ACCESS_DENIED_ACE_TYPE : fRes = ::AddAccessDeniedAceEx ( pACL, ACL_REVISION, dwAceFlags, dwAccessMask , pPrincipalSid ); break;
  657. case ACCESS_DENIED_OBJECT_ACE_TYPE : fRes = ::AddAccessDeniedObjectAce ( pACL, ACL_REVISION, dwAceFlags, dwAccessMask, guidObjectType, guidInheritedObjectType, pPrincipalSid ); break;
  658. case SYSTEM_AUDIT_ACE_TYPE : fRes = ::AddAuditAccessAceEx ( pACL, ACL_REVISION, dwAceFlags, dwAccessMask , pPrincipalSid, TRUE, TRUE ); break;
  659. case SYSTEM_AUDIT_OBJECT_ACE_TYPE : fRes = ::AddAuditAccessObjectAce ( pACL, ACL_REVISION, dwAceFlags, dwAccessMask, guidObjectType, guidInheritedObjectType, pPrincipalSid, TRUE, TRUE ); break;
  660. }
  661. if(fRes == FALSE)
  662. {
  663. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ::GetLastError());
  664. }
  665. hr = S_OK;
  666. __MPC_FUNC_CLEANUP;
  667. __MPC_FUNC_EXIT(hr);
  668. }
  669. ////////////////////////////////////////////////////////////////////////////////
  670. ////////////////////////////////////////////////////////////////////////////////
  671. MPC::SecurityDescriptor::SecurityDescriptor()
  672. {
  673. m_pSD = NULL; // PSECURITY_DESCRIPTOR m_pSD;
  674. m_pOwner = NULL; // PSID m_pOwner;
  675. m_bOwnerDefaulted = TRUE; // BOOL m_bOwnerDefaulted;
  676. m_pGroup = NULL; // PSID m_pGroup;
  677. m_bGroupDefaulted = TRUE; // BOOL m_bGroupDefaulted;
  678. m_pDACL = NULL; // PACL m_pDACL;
  679. m_bDaclDefaulted = TRUE; // BOOL m_bDaclDefaulted;
  680. m_pSACL = NULL; // PACL m_pSACL;
  681. m_bSaclDefaulted = TRUE; // BOOL m_bSaclDefaulted;
  682. }
  683. MPC::SecurityDescriptor::~SecurityDescriptor()
  684. {
  685. CleanUp();
  686. }
  687. void MPC::SecurityDescriptor::CleanUp()
  688. {
  689. ReleaseMemory( (void*&)m_pSD );
  690. ReleaseMemory( (void*&)m_pOwner );
  691. ReleaseMemory( (void*&)m_pGroup );
  692. ReleaseMemory( (void*&)m_pDACL );
  693. ReleaseMemory( (void*&)m_pSACL );
  694. m_bOwnerDefaulted = TRUE;
  695. m_bGroupDefaulted = TRUE;
  696. m_bDaclDefaulted = TRUE;
  697. m_bSaclDefaulted = TRUE;
  698. }
  699. ////////////////////////////////////////////////////////////////////////////////
  700. HRESULT MPC::SecurityDescriptor::Initialize()
  701. {
  702. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::Initialize" );
  703. HRESULT hr;
  704. CleanUp();
  705. __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)m_pSD, sizeof(SECURITY_DESCRIPTOR) ));
  706. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::InitializeSecurityDescriptor( m_pSD, SECURITY_DESCRIPTOR_REVISION ));
  707. //
  708. // Set the DACL to allow EVERYONE.
  709. //
  710. #pragma prefast(suppress:248, this is a base class, derived classes are responsible for setting the appropriate DACL (PREfast bug 516684))
  711. ::SetSecurityDescriptorDacl( m_pSD, TRUE, NULL, FALSE );
  712. hr = S_OK;
  713. __MPC_FUNC_CLEANUP;
  714. __MPC_FUNC_EXIT(hr);
  715. }
  716. HRESULT MPC::SecurityDescriptor::InitializeFromProcessToken( /*[in]*/ BOOL bDefaulted )
  717. {
  718. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::InitializeFromProcessToken" );
  719. HRESULT hr;
  720. PSID pUserSid = NULL;
  721. PSID pGroupSid = NULL;
  722. __MPC_EXIT_IF_METHOD_FAILS(hr, Initialize());
  723. __MPC_EXIT_IF_METHOD_FAILS(hr, GetProcessSids( &pUserSid, &pGroupSid ));
  724. __MPC_EXIT_IF_METHOD_FAILS(hr, SetOwner( pUserSid , bDefaulted ));
  725. __MPC_EXIT_IF_METHOD_FAILS(hr, SetGroup( pGroupSid, bDefaulted ));
  726. hr = S_OK;
  727. __MPC_FUNC_CLEANUP;
  728. ReleaseMemory( pUserSid );
  729. ReleaseMemory( pGroupSid );
  730. __MPC_FUNC_EXIT(hr);
  731. }
  732. HRESULT MPC::SecurityDescriptor::InitializeFromThreadToken( /*[in]*/ BOOL bDefaulted ,
  733. /*[in]*/ BOOL bRevertToProcessToken )
  734. {
  735. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::InitializeFromThreadToken" );
  736. HRESULT hr;
  737. PSID pUserSid = NULL;
  738. PSID pGroupSid = NULL;
  739. __MPC_EXIT_IF_METHOD_FAILS(hr, Initialize());
  740. if(FAILED(hr = GetThreadSids( &pUserSid, &pGroupSid )))
  741. {
  742. if(HRESULT_CODE(hr) == ERROR_NO_TOKEN && bRevertToProcessToken)
  743. {
  744. __MPC_EXIT_IF_METHOD_FAILS(hr, GetProcessSids( &pUserSid, &pGroupSid ));
  745. }
  746. else
  747. {
  748. __MPC_FUNC_LEAVE;
  749. }
  750. }
  751. __MPC_EXIT_IF_METHOD_FAILS(hr, SetOwner( pUserSid , bDefaulted ));
  752. __MPC_EXIT_IF_METHOD_FAILS(hr, SetGroup( pGroupSid, bDefaulted ));
  753. hr = S_OK;
  754. __MPC_FUNC_CLEANUP;
  755. ReleaseMemory( pUserSid );
  756. ReleaseMemory( pGroupSid );
  757. __MPC_FUNC_EXIT(hr);
  758. }
  759. ////////////////////////////////////////////////////////////////////////////////
  760. HRESULT MPC::SecurityDescriptor::ConvertFromString( /*[in]*/ LPCWSTR szSD )
  761. {
  762. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::ConvertFromString" );
  763. HRESULT hr;
  764. PSECURITY_DESCRIPTOR pSD = NULL;
  765. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::ConvertStringSecurityDescriptorToSecurityDescriptorW( szSD, SDDL_REVISION_1, &pSD, NULL ));
  766. __MPC_EXIT_IF_METHOD_FAILS(hr, Attach( pSD ));
  767. hr = S_OK;
  768. __MPC_FUNC_CLEANUP;
  769. if(pSD) ::LocalFree( pSD );
  770. __MPC_FUNC_EXIT(hr);
  771. }
  772. HRESULT MPC::SecurityDescriptor::ConvertToString( /*[out]*/ BSTR *pbstrSD )
  773. {
  774. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::ConvertToString" );
  775. HRESULT hr;
  776. LPWSTR szSD = NULL;
  777. __MPC_PARAMCHECK_BEGIN(hr)
  778. __MPC_PARAMCHECK_POINTER_AND_SET(pbstrSD,NULL);
  779. __MPC_PARAMCHECK_END();
  780. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::ConvertSecurityDescriptorToStringSecurityDescriptorW( m_pSD, SDDL_REVISION_1, s_SecInfo_ALL, &szSD, NULL ));
  781. *pbstrSD = ::SysAllocString( szSD );
  782. hr = S_OK;
  783. __MPC_FUNC_CLEANUP;
  784. if(szSD) ::LocalFree( szSD );
  785. __MPC_FUNC_EXIT(hr);
  786. }
  787. ////////////////////////////////////////////////////////////////////////////////
  788. HRESULT MPC::SecurityDescriptor::Attach( /*[in]*/ PSECURITY_DESCRIPTOR pSelfRelativeSD )
  789. {
  790. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::Attach" );
  791. HRESULT hr;
  792. PSID pOwnerSid;
  793. PSID pGroupSid;
  794. PACL pDACL;
  795. PACL pSACL;
  796. BOOL bDefaulted;
  797. BOOL bPresent;
  798. ACCESS_ALLOWED_ACE* pACE;
  799. SECURITY_DESCRIPTOR_CONTROL sdcFlags;
  800. DWORD dwRev;
  801. __MPC_EXIT_IF_METHOD_FAILS(hr, Initialize());
  802. if(pSelfRelativeSD == NULL) // Empty SD?
  803. {
  804. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  805. }
  806. //
  807. // Copy flags of interest.
  808. //
  809. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetSecurityDescriptorControl( pSelfRelativeSD , &sdcFlags, &dwRev ));
  810. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetSecurityDescriptorControl( m_pSD, s_sdcMask, sdcFlags & s_sdcMask ));
  811. //
  812. // Copy owner and group.
  813. //
  814. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetSecurityDescriptorOwner( pSelfRelativeSD, &pOwnerSid, &bDefaulted ));
  815. __MPC_EXIT_IF_METHOD_FAILS(hr, SetOwner( pOwnerSid, bDefaulted ));
  816. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetSecurityDescriptorGroup( pSelfRelativeSD, &pGroupSid, &bDefaulted ));
  817. __MPC_EXIT_IF_METHOD_FAILS(hr, SetGroup( pGroupSid, bDefaulted ));
  818. //
  819. // Copy the existing DACL.
  820. //
  821. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetSecurityDescriptorDacl( pSelfRelativeSD, &bPresent, &pDACL, &m_bDaclDefaulted ));
  822. if(bPresent)
  823. {
  824. __MPC_EXIT_IF_METHOD_FAILS(hr, CloneACL( m_pDACL, pDACL ));
  825. //
  826. // set the DACL
  827. //
  828. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetSecurityDescriptorDacl( m_pSD, m_pDACL ? TRUE : FALSE, m_pDACL, m_bDaclDefaulted ));
  829. }
  830. //
  831. // Copy the existing SACL.
  832. //
  833. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetSecurityDescriptorSacl( pSelfRelativeSD, &bPresent, &pSACL, &m_bSaclDefaulted ));
  834. if(bPresent)
  835. {
  836. __MPC_EXIT_IF_METHOD_FAILS(hr, CloneACL( m_pSACL, pSACL ));
  837. // set the SACL
  838. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetSecurityDescriptorSacl(m_pSD, m_pSACL ? TRUE : FALSE, m_pSACL, m_bSaclDefaulted ));
  839. }
  840. if(m_pSD)
  841. {
  842. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::IsValidSecurityDescriptor( m_pSD ));
  843. }
  844. hr = S_OK;
  845. __MPC_FUNC_CLEANUP;
  846. __MPC_FUNC_EXIT(hr);
  847. }
  848. HRESULT MPC::SecurityDescriptor::AttachObject( /*[in]*/ HANDLE hObject, /*[in]*/ SECURITY_INFORMATION secInfo )
  849. {
  850. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::AttachObject" );
  851. HRESULT hr;
  852. DWORD dwRes;
  853. DWORD dwSize;
  854. PSECURITY_DESCRIPTOR pSD = NULL;
  855. ::GetKernelObjectSecurity( hObject, secInfo, pSD, 0, &dwSize );
  856. if((dwRes = ::GetLastError()) != ERROR_INSUFFICIENT_BUFFER)
  857. {
  858. if(dwRes == ERROR_SUCCESS)
  859. {
  860. __MPC_SET_ERROR_AND_EXIT(hr, Initialize()); // Empty SD.
  861. }
  862. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes);
  863. }
  864. __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( pSD, dwSize ));
  865. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetKernelObjectSecurity( hObject, secInfo, pSD, dwSize, &dwSize ));
  866. __MPC_EXIT_IF_METHOD_FAILS(hr, Attach( pSD ));
  867. hr = S_OK;
  868. __MPC_FUNC_CLEANUP;
  869. ReleaseMemory( pSD );
  870. __MPC_FUNC_EXIT(hr);
  871. }
  872. ////////////////////////////////////////////////////////////////////////////////
  873. HRESULT MPC::SecurityDescriptor::GetControl( /*[out]*/ SECURITY_DESCRIPTOR_CONTROL& sdc )
  874. {
  875. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::GetControl" );
  876. HRESULT hr;
  877. DWORD dwRev;
  878. ATLASSERT(m_pSD);
  879. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetSecurityDescriptorControl( m_pSD, &sdc, &dwRev ));
  880. hr = S_OK;
  881. __MPC_FUNC_CLEANUP;
  882. __MPC_FUNC_EXIT(hr);
  883. }
  884. HRESULT MPC::SecurityDescriptor::SetControl( /*[in ]*/ SECURITY_DESCRIPTOR_CONTROL sdc )
  885. {
  886. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::SetControl" );
  887. HRESULT hr;
  888. ATLASSERT(m_pSD);
  889. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetSecurityDescriptorControl( m_pSD, s_sdcMask, s_sdcMask & sdc ));
  890. hr = S_OK;
  891. __MPC_FUNC_CLEANUP;
  892. __MPC_FUNC_EXIT(hr);
  893. }
  894. HRESULT MPC::SecurityDescriptor::SetOwner( /*[in]*/ PSID pOwnerSid ,
  895. /*[in]*/ BOOL bDefaulted )
  896. {
  897. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::SetOwner" );
  898. HRESULT hr;
  899. ATLASSERT(m_pSD);
  900. m_bOwnerDefaulted = bDefaulted;
  901. //
  902. // Mark the SD as having no owner
  903. //
  904. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetSecurityDescriptorOwner( m_pSD, NULL, bDefaulted ));
  905. ReleaseMemory( m_pOwner );
  906. if(pOwnerSid)
  907. {
  908. // Make a copy of the Sid for the return value
  909. DWORD dwSize = ::GetLengthSid( pOwnerSid );
  910. __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( m_pOwner, dwSize ));
  911. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CopySid( dwSize, m_pOwner, pOwnerSid ));
  912. ATLASSERT(::IsValidSid( m_pOwner ));
  913. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetSecurityDescriptorOwner( m_pSD, m_pOwner, bDefaulted ));
  914. }
  915. hr = S_OK;
  916. __MPC_FUNC_CLEANUP;
  917. __MPC_FUNC_EXIT(hr);
  918. }
  919. HRESULT MPC::SecurityDescriptor::SetOwner( /*[in]*/ LPCWSTR szOwnerName ,
  920. /*[in]*/ BOOL bDefaulted )
  921. {
  922. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::SetOwner" );
  923. HRESULT hr;
  924. PSID pOwnerSid = NULL;
  925. __MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( szOwnerName, pOwnerSid ));
  926. __MPC_EXIT_IF_METHOD_FAILS(hr, SetOwner( pOwnerSid, bDefaulted ));
  927. hr = S_OK;
  928. __MPC_FUNC_CLEANUP;
  929. ReleaseMemory( (void*&)pOwnerSid );
  930. __MPC_FUNC_EXIT(hr);
  931. }
  932. HRESULT MPC::SecurityDescriptor::SetGroup( /*[in]*/ PSID pGroupSid ,
  933. /*[in]*/ BOOL bDefaulted )
  934. {
  935. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::SetGroup" );
  936. HRESULT hr;
  937. ATLASSERT(m_pSD);
  938. m_bGroupDefaulted = bDefaulted;
  939. //
  940. // Mark the SD as having no owner
  941. //
  942. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetSecurityDescriptorGroup( m_pSD, NULL, bDefaulted ));
  943. ReleaseMemory( m_pGroup );
  944. if(pGroupSid)
  945. {
  946. // Make a copy of the Sid for the return value
  947. DWORD dwSize = ::GetLengthSid( pGroupSid );
  948. __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( m_pGroup, dwSize ));
  949. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CopySid( dwSize, m_pGroup, pGroupSid ));
  950. ATLASSERT(::IsValidSid( m_pGroup ));
  951. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetSecurityDescriptorGroup( m_pSD, m_pGroup, bDefaulted ));
  952. }
  953. hr = S_OK;
  954. __MPC_FUNC_CLEANUP;
  955. __MPC_FUNC_EXIT(hr);
  956. }
  957. HRESULT MPC::SecurityDescriptor::SetGroup( /*[in]*/ LPCWSTR szGroupName ,
  958. /*[in]*/ BOOL bDefaulted )
  959. {
  960. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::SetGroup" );
  961. HRESULT hr;
  962. PSID pGroupSid = NULL;
  963. __MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( szGroupName, pGroupSid ));
  964. __MPC_EXIT_IF_METHOD_FAILS(hr, SetGroup( pGroupSid, bDefaulted ));
  965. hr = S_OK;
  966. __MPC_FUNC_CLEANUP;
  967. ReleaseMemory( (void*&)pGroupSid );
  968. __MPC_FUNC_EXIT(hr);
  969. }
  970. ////////////////////////////////////////////////////////////////////////////////
  971. HRESULT MPC::SecurityDescriptor::Remove( /*[in]*/ PSID pPrincipalSid ,
  972. /*[in]*/ int pos )
  973. {
  974. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::Remove" );
  975. HRESULT hr;
  976. ATLASSERT(m_pSD);
  977. __MPC_EXIT_IF_METHOD_FAILS(hr, RemovePrincipalFromACL( m_pDACL, pPrincipalSid, pos ));
  978. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetSecurityDescriptorDacl( m_pSD, TRUE, m_pDACL, FALSE ));
  979. hr = S_OK;
  980. __MPC_FUNC_CLEANUP;
  981. __MPC_FUNC_EXIT(hr);
  982. }
  983. HRESULT MPC::SecurityDescriptor::Remove( /*[in]*/ LPCWSTR szPrincipal ,
  984. /*[in]*/ int pos )
  985. {
  986. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::Remove" );
  987. HRESULT hr;
  988. PSID pPrincipalSid = NULL;
  989. __MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( szPrincipal, pPrincipalSid ));
  990. __MPC_EXIT_IF_METHOD_FAILS(hr, Remove( pPrincipalSid, pos ));
  991. hr = S_OK;
  992. __MPC_FUNC_CLEANUP;
  993. ReleaseMemory( (void*&)pPrincipalSid );
  994. __MPC_FUNC_EXIT(hr);
  995. }
  996. HRESULT MPC::SecurityDescriptor::Add( /*[in]*/ PSID pPrincipalSid ,
  997. /*[in]*/ DWORD dwAceType ,
  998. /*[in]*/ DWORD dwAceFlags ,
  999. /*[in]*/ DWORD dwAccessMask ,
  1000. /*[in]*/ GUID* guidObjectType ,
  1001. /*[in]*/ GUID* guidInheritedObjectType )
  1002. {
  1003. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::Add" );
  1004. HRESULT hr;
  1005. ATLASSERT(m_pSD);
  1006. __MPC_EXIT_IF_METHOD_FAILS(hr, AddACEToACL( m_pDACL, pPrincipalSid, dwAceType, dwAceFlags, dwAccessMask, guidObjectType, guidInheritedObjectType ));
  1007. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetSecurityDescriptorDacl( m_pSD, TRUE, m_pDACL, FALSE ));
  1008. m_bDaclDefaulted = FALSE;
  1009. hr = S_OK;
  1010. __MPC_FUNC_CLEANUP;
  1011. __MPC_FUNC_EXIT(hr);
  1012. }
  1013. HRESULT MPC::SecurityDescriptor::Add( /*[in]*/ LPCWSTR szPrincipal ,
  1014. /*[in]*/ DWORD dwAceType ,
  1015. /*[in]*/ DWORD dwAceFlags ,
  1016. /*[in]*/ DWORD dwAccessMask ,
  1017. /*[in]*/ GUID* guidObjectType ,
  1018. /*[in]*/ GUID* guidInheritedObjectType )
  1019. {
  1020. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::Add" );
  1021. HRESULT hr;
  1022. PSID pPrincipalSid = NULL;
  1023. __MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( szPrincipal, pPrincipalSid ));
  1024. __MPC_EXIT_IF_METHOD_FAILS(hr, Add( pPrincipalSid, dwAceType, dwAceFlags, dwAccessMask, guidObjectType, guidInheritedObjectType ));
  1025. hr = S_OK;
  1026. __MPC_FUNC_CLEANUP;
  1027. ReleaseMemory( (void*&)pPrincipalSid );
  1028. __MPC_FUNC_EXIT(hr);
  1029. }
  1030. ////////////////////////////////////////////////////////////////////////////////
  1031. HRESULT MPC::SecurityDescriptor::GetForFile( /*[in]*/ LPCWSTR szFilename ,
  1032. /*[in]*/ SECURITY_INFORMATION secInfo )
  1033. {
  1034. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::GetForFile" );
  1035. HRESULT hr;
  1036. PSECURITY_DESCRIPTOR pSD = NULL;
  1037. DWORD dwLen = 0;
  1038. DWORD dwRes;
  1039. __MPC_PARAMCHECK_BEGIN(hr)
  1040. __MPC_PARAMCHECK_STRING_NOT_EMPTY(szFilename);
  1041. __MPC_PARAMCHECK_END();
  1042. //
  1043. // Get the security descriptor for the file.
  1044. //
  1045. ::GetFileSecurityW( szFilename, secInfo, NULL, 0, &dwLen );
  1046. if((dwRes = ::GetLastError()) != ERROR_INSUFFICIENT_BUFFER)
  1047. {
  1048. if(dwRes == ERROR_SUCCESS)
  1049. {
  1050. __MPC_SET_ERROR_AND_EXIT(hr, Initialize()); // Empty SD.
  1051. }
  1052. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes);
  1053. }
  1054. __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (LPVOID&)pSD, dwLen ));
  1055. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetFileSecurityW( szFilename, secInfo, pSD, dwLen, &dwLen ));
  1056. __MPC_EXIT_IF_METHOD_FAILS(hr, Attach( pSD ));
  1057. hr = S_OK;
  1058. __MPC_FUNC_CLEANUP;
  1059. ReleaseMemory( (void*&)pSD );
  1060. __MPC_FUNC_EXIT(hr);
  1061. }
  1062. HRESULT MPC::SecurityDescriptor::SetForFile( /*[in]*/ LPCWSTR szFilename ,
  1063. /*[in]*/ SECURITY_INFORMATION secInfo )
  1064. {
  1065. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::SetForFile" );
  1066. HRESULT hr;
  1067. __MPC_PARAMCHECK_BEGIN(hr)
  1068. __MPC_PARAMCHECK_STRING_NOT_EMPTY(szFilename);
  1069. __MPC_PARAMCHECK_END();
  1070. //
  1071. // Set the security descriptor for the file.
  1072. //
  1073. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetFileSecurityW( szFilename, secInfo, GetSD() ));
  1074. hr = S_OK;
  1075. __MPC_FUNC_CLEANUP;
  1076. __MPC_FUNC_EXIT(hr);
  1077. }
  1078. HRESULT MPC::SecurityDescriptor::GetForRegistry( /*[in]*/ LPCWSTR szKey ,
  1079. /*[in]*/ SECURITY_INFORMATION secInfo ,
  1080. /*[in]*/ HKEY hKeyRoot )
  1081. {
  1082. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::GetForRegistry" );
  1083. HRESULT hr;
  1084. HKEY hKey = NULL;
  1085. PSECURITY_DESCRIPTOR pSD = NULL;
  1086. DWORD dwLen;
  1087. DWORD dwRes;
  1088. __MPC_PARAMCHECK_BEGIN(hr)
  1089. __MPC_PARAMCHECK_STRING_NOT_EMPTY(szKey);
  1090. __MPC_PARAMCHECK_END();
  1091. if(hKeyRoot == NULL)
  1092. {
  1093. //
  1094. // Extract the hive from the string....
  1095. //
  1096. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::RegKey::ParsePath( szKey, hKeyRoot, szKey ));
  1097. }
  1098. __MPC_EXIT_IF_SYSCALL_FAILS(hr, dwRes, ::RegOpenKeyExW( hKeyRoot, szKey, 0, Local_GenerateAccessMask( secInfo, true ), &hKey ));
  1099. //
  1100. // Get the security descriptor for the registry key.
  1101. //
  1102. dwLen = 0;
  1103. dwRes = ::RegGetKeySecurity( hKey, secInfo, NULL, &dwLen );
  1104. if(dwRes != ERROR_INSUFFICIENT_BUFFER)
  1105. {
  1106. if(dwRes == ERROR_SUCCESS)
  1107. {
  1108. __MPC_SET_ERROR_AND_EXIT(hr, Initialize()); // Empty SD.
  1109. }
  1110. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes);
  1111. }
  1112. __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (LPVOID&)pSD, dwLen ));
  1113. __MPC_EXIT_IF_SYSCALL_FAILS(hr, dwRes, ::RegGetKeySecurity( hKey, secInfo, pSD, &dwLen ));
  1114. __MPC_EXIT_IF_METHOD_FAILS(hr, Attach( pSD ));
  1115. hr = S_OK;
  1116. __MPC_FUNC_CLEANUP;
  1117. ReleaseMemory( (void*&)pSD );
  1118. if(hKey) ::RegCloseKey( hKey );
  1119. __MPC_FUNC_EXIT(hr);
  1120. }
  1121. HRESULT MPC::SecurityDescriptor::SetForRegistry( /*[in]*/ LPCWSTR szKey ,
  1122. /*[in]*/ SECURITY_INFORMATION secInfo ,
  1123. /*[in]*/ HKEY hKeyRoot )
  1124. {
  1125. __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::SetForRegistry" );
  1126. HRESULT hr;
  1127. HKEY hKey = NULL;
  1128. DWORD dwRes;
  1129. __MPC_PARAMCHECK_BEGIN(hr)
  1130. __MPC_PARAMCHECK_STRING_NOT_EMPTY(szKey);
  1131. __MPC_PARAMCHECK_END();
  1132. if(hKeyRoot == NULL)
  1133. {
  1134. //
  1135. // Extract the hive from the string....
  1136. //
  1137. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::RegKey::ParsePath( szKey, hKeyRoot, szKey ));
  1138. }
  1139. __MPC_EXIT_IF_SYSCALL_FAILS(hr, dwRes, ::RegOpenKeyExW( hKeyRoot, szKey, 0, Local_GenerateAccessMask( secInfo, false ), &hKey ));
  1140. //
  1141. // Set the security descriptor for the registry key.
  1142. //
  1143. __MPC_EXIT_IF_SYSCALL_FAILS(hr, dwRes, ::RegSetKeySecurity( hKey, secInfo, GetSD() ));
  1144. hr = S_OK;
  1145. __MPC_FUNC_CLEANUP;
  1146. if(hKey) ::RegCloseKey( hKey );
  1147. __MPC_FUNC_EXIT(hr);
  1148. }
  1149. ////////////////////////////////////////////////////////////////////////////////
  1150. ////////////////////////////////////////////////////////////////////////////////
  1151. ////////////////////////////////////////////////////////////////////////////////
  1152. MPC::Impersonation::Impersonation()
  1153. {
  1154. m_hToken = NULL; // HANDLE m_hToken;
  1155. m_fImpersonating = false; // bool m_fImpersonating;
  1156. }
  1157. MPC::Impersonation::Impersonation( /*[in]*/ const MPC::Impersonation& imp )
  1158. {
  1159. m_hToken = NULL; // HANDLE m_hToken;
  1160. m_fImpersonating = false; // bool m_fImpersonating;
  1161. *this = imp;
  1162. }
  1163. MPC::Impersonation::~Impersonation()
  1164. {
  1165. Release();
  1166. }
  1167. MPC::Impersonation& MPC::Impersonation::operator=( /*[in]*/ const MPC::Impersonation& imp )
  1168. {
  1169. Release();
  1170. if(!::DuplicateHandle( ::GetCurrentProcess(), imp.m_hToken,
  1171. ::GetCurrentProcess(), & m_hToken, 0, FALSE, DUPLICATE_SAME_ACCESS ))
  1172. {
  1173. ; // Error...
  1174. }
  1175. return *this;
  1176. }
  1177. ////////////////////////////////////////////////////////////////////////////////
  1178. void MPC::Impersonation::Release()
  1179. {
  1180. (void)RevertToSelf();
  1181. if(m_hToken)
  1182. {
  1183. ::CloseHandle( m_hToken ); m_hToken = NULL;
  1184. }
  1185. }
  1186. HRESULT MPC::Impersonation::Initialize( DWORD dwDesiredAccess )
  1187. {
  1188. __MPC_FUNC_ENTRY( COMMONID, "MPC::Impersonation::Initialize" );
  1189. HRESULT hr;
  1190. CComPtr<IServerSecurity> ss;
  1191. bool fRevert = false;
  1192. Release();
  1193. __MPC_EXIT_IF_METHOD_FAILS(hr, ::CoGetCallContext( IID_IServerSecurity, (void**)&ss ));
  1194. __MPC_EXIT_IF_METHOD_FAILS(hr, ss->ImpersonateClient()); fRevert = true;
  1195. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::OpenThreadToken( ::GetCurrentThread(), dwDesiredAccess, TRUE, &m_hToken ));
  1196. hr = S_OK;
  1197. __MPC_FUNC_CLEANUP;
  1198. if(fRevert && ss) ss->RevertToSelf();
  1199. __MPC_FUNC_EXIT(hr);
  1200. }
  1201. void MPC::Impersonation::Attach( /*[in]*/ HANDLE hToken )
  1202. {
  1203. Release();
  1204. m_hToken = hToken;
  1205. }
  1206. HANDLE MPC::Impersonation::Detach()
  1207. {
  1208. HANDLE hToken = m_hToken;
  1209. (void)RevertToSelf();
  1210. m_hToken = NULL;
  1211. return hToken;
  1212. }
  1213. HRESULT MPC::Impersonation::Impersonate()
  1214. {
  1215. __MPC_FUNC_ENTRY( COMMONID, "MPC::Impersonation::Impersonate" );
  1216. HRESULT hr;
  1217. __MPC_PARAMCHECK_BEGIN(hr)
  1218. __MPC_PARAMCHECK_NOTNULL(m_hToken);
  1219. __MPC_PARAMCHECK_END();
  1220. if(m_fImpersonating == false)
  1221. {
  1222. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetThreadToken( NULL, m_hToken ));
  1223. m_fImpersonating = true;
  1224. }
  1225. hr = S_OK;
  1226. __MPC_FUNC_CLEANUP;
  1227. __MPC_FUNC_EXIT(hr);
  1228. }
  1229. HRESULT MPC::Impersonation::RevertToSelf()
  1230. {
  1231. __MPC_FUNC_ENTRY( COMMONID, "MPC::Impersonation::RevertToSelf" );
  1232. HRESULT hr;
  1233. if(m_fImpersonating)
  1234. {
  1235. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetThreadToken( NULL, NULL ));
  1236. m_fImpersonating = false;
  1237. }
  1238. hr = S_OK;
  1239. __MPC_FUNC_CLEANUP;
  1240. __MPC_FUNC_EXIT(hr);
  1241. }
  1242. ////////////////////////////////////////////////////////////////////////////////
  1243. ////////////////////////////////////////////////////////////////////////////////
  1244. ////////////////////////////////////////////////////////////////////////////////
  1245. MPC::AccessCheck::AccessCheck()
  1246. {
  1247. m_hToken = NULL; // HANDLE m_hToken;
  1248. }
  1249. MPC::AccessCheck::~AccessCheck()
  1250. {
  1251. Release();
  1252. }
  1253. void MPC::AccessCheck::Release()
  1254. {
  1255. if(m_hToken)
  1256. {
  1257. ::CloseHandle( m_hToken ); m_hToken = NULL;
  1258. }
  1259. }
  1260. HRESULT MPC::AccessCheck::GetTokenFromImpersonation()
  1261. {
  1262. __MPC_FUNC_ENTRY( COMMONID, "MPC::AccessCheck::GetTokenFromImpersonation" );
  1263. HRESULT hr;
  1264. MPC::Impersonation imp;
  1265. Release();
  1266. __MPC_EXIT_IF_METHOD_FAILS(hr, imp.Initialize( TOKEN_QUERY ));
  1267. m_hToken = imp.Detach();
  1268. hr = S_OK;
  1269. __MPC_FUNC_CLEANUP;
  1270. __MPC_FUNC_EXIT(hr);
  1271. }
  1272. void MPC::AccessCheck::Attach( /*[in]*/ HANDLE hToken )
  1273. {
  1274. Release();
  1275. m_hToken = hToken;
  1276. }
  1277. HANDLE MPC::AccessCheck::Detach()
  1278. {
  1279. HANDLE hToken = m_hToken;
  1280. m_hToken = NULL;
  1281. return hToken;
  1282. }
  1283. HRESULT MPC::AccessCheck::Verify( /*[in ]*/ DWORD dwDesired ,
  1284. /*[out]*/ BOOL& fGranted ,
  1285. /*[out]*/ DWORD& dwGranted ,
  1286. /*[in ]*/ PSECURITY_DESCRIPTOR sd )
  1287. {
  1288. __MPC_FUNC_ENTRY( COMMONID, "MPC::AccessCheck::Verify" );
  1289. HRESULT hr;
  1290. PRIVILEGE_SET PrivilegeSet;
  1291. DWORD dwPrivSetSize = sizeof( PRIVILEGE_SET );
  1292. GENERIC_MAPPING ObjMap =
  1293. {
  1294. ACCESS_READ ,
  1295. ACCESS_WRITE,
  1296. ACCESS_NONE ,
  1297. ACCESS_ALL
  1298. };
  1299. fGranted = FALSE;
  1300. if(sd == NULL || !::IsValidSecurityDescriptor( sd ) )
  1301. {
  1302. __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
  1303. }
  1304. //
  1305. // This only does something if we specify generic access rights
  1306. // like GENERIC_ALL. We are not.
  1307. //
  1308. ::MapGenericMask( &dwDesired, &ObjMap );
  1309. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::AccessCheck( sd ,
  1310. m_hToken ,
  1311. dwDesired ,
  1312. &ObjMap ,
  1313. &PrivilegeSet ,
  1314. &dwPrivSetSize ,
  1315. &dwGranted ,
  1316. &fGranted ));
  1317. hr = S_OK;
  1318. __MPC_FUNC_CLEANUP;
  1319. __MPC_FUNC_EXIT(hr);
  1320. }
  1321. HRESULT MPC::AccessCheck::Verify( /*[in ]*/ DWORD dwDesired ,
  1322. /*[out]*/ BOOL& fGranted ,
  1323. /*[out]*/ DWORD& dwGranted ,
  1324. /*[in ]*/ MPC::SecurityDescriptor& sd )
  1325. {
  1326. __MPC_FUNC_ENTRY( COMMONID, "MPC::AccessCheck::Verify" );
  1327. HRESULT hr;
  1328. __MPC_EXIT_IF_METHOD_FAILS(hr, Verify( dwDesired, fGranted, dwGranted, sd.GetSD() ));
  1329. hr = S_OK;
  1330. __MPC_FUNC_CLEANUP;
  1331. __MPC_FUNC_EXIT(hr);
  1332. }
  1333. HRESULT MPC::AccessCheck::Verify( /*[in ]*/ DWORD dwDesired ,
  1334. /*[out]*/ BOOL& fGranted ,
  1335. /*[out]*/ DWORD& dwGranted ,
  1336. /*[in ]*/ LPCWSTR sd )
  1337. {
  1338. __MPC_FUNC_ENTRY( COMMONID, "MPC::AccessCheck::Verify" );
  1339. HRESULT hr;
  1340. MPC::SecurityDescriptor sdd;
  1341. __MPC_EXIT_IF_METHOD_FAILS(hr, sdd.ConvertFromString( sd ));
  1342. __MPC_EXIT_IF_METHOD_FAILS(hr, Verify( dwDesired, fGranted, dwGranted, sdd.GetSD() ));
  1343. hr = S_OK;
  1344. __MPC_FUNC_CLEANUP;
  1345. __MPC_FUNC_EXIT(hr);
  1346. }
  1347. ////////////////////////////////////////////////////////////////////////////////
  1348. ////////////////////////////////////////////////////////////////////////////////
  1349. ////////////////////////////////////////////////////////////////////////////////
  1350. HRESULT MPC::ChangeSD( /*[in]*/ MPC::SecurityDescriptor& sdd ,
  1351. /*[in]*/ MPC::FileSystemObject& fso ,
  1352. /*[in]*/ SECURITY_INFORMATION secInfo ,
  1353. /*[in]*/ bool fDeep ,
  1354. /*[in]*/ bool fApplyToDirs ,
  1355. /*[in]*/ bool fApplyToFiles )
  1356. {
  1357. __MPC_FUNC_ENTRY( COMMONID, "MPC::ChangeSD" );
  1358. HRESULT hr;
  1359. MPC::wstring szPath;
  1360. MPC::FileSystemObject::List lst;
  1361. MPC::FileSystemObject::Iter it;
  1362. __MPC_EXIT_IF_METHOD_FAILS(hr, fso.get_Path( szPath ));
  1363. if((fApplyToDirs && fso.IsDirectory()) ||
  1364. (fApplyToFiles && fso.IsFile ()) )
  1365. {
  1366. //
  1367. // Set the security descriptor for the object.
  1368. //
  1369. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetFileSecurityW( szPath.c_str(), secInfo, sdd.GetSD() ));
  1370. }
  1371. if(fDeep)
  1372. {
  1373. __MPC_EXIT_IF_METHOD_FAILS(hr, fso.EnumerateFiles( lst ));
  1374. for(it=lst.begin(); it != lst.end(); it++)
  1375. {
  1376. __MPC_EXIT_IF_METHOD_FAILS(hr, ChangeSD( sdd, *(*it), secInfo, true, fApplyToDirs, fApplyToFiles ));
  1377. }
  1378. __MPC_EXIT_IF_METHOD_FAILS(hr, fso.EnumerateFolders( lst ));
  1379. for(it=lst.begin(); it != lst.end(); it++)
  1380. {
  1381. __MPC_EXIT_IF_METHOD_FAILS(hr, ChangeSD( sdd, *(*it), secInfo, true, fApplyToDirs, fApplyToFiles ));
  1382. }
  1383. }
  1384. hr = S_OK;
  1385. __MPC_FUNC_CLEANUP;
  1386. __MPC_FUNC_EXIT(hr);
  1387. }
  1388. HRESULT MPC::ChangeSD( /*[in]*/ MPC::SecurityDescriptor& sdd ,
  1389. /*[in]*/ LPCWSTR szRoot ,
  1390. /*[in]*/ SECURITY_INFORMATION secInfo ,
  1391. /*[in]*/ bool fDeep ,
  1392. /*[in]*/ bool fApplyToDirs ,
  1393. /*[in]*/ bool fApplyToFiles )
  1394. {
  1395. __MPC_FUNC_ENTRY( COMMONID, "MPC::ChangeSD" );
  1396. HRESULT hr;
  1397. MPC::wstring strRoot( szRoot ); MPC::SubstituteEnvVariables( strRoot );
  1398. MPC::FileSystemObject fso ( strRoot.c_str() );
  1399. __MPC_EXIT_IF_METHOD_FAILS(hr, fso.CreateDir( true ));
  1400. __MPC_EXIT_IF_METHOD_FAILS(hr, ChangeSD( sdd, fso, secInfo, fDeep, fApplyToDirs, fApplyToFiles ));
  1401. hr = S_OK;
  1402. __MPC_FUNC_CLEANUP;
  1403. __MPC_FUNC_EXIT(hr);
  1404. }
  1405. ////////////////////////////////////////////////////////////////////////////////
  1406. ////////////////////////////////////////////////////////////////////////////////
  1407. ////////////////////////////////////////////////////////////////////////////////
  1408. HRESULT MPC::GetCallerPrincipal( /*[in ]*/ bool fImpersonate ,
  1409. /*[out]*/ CComBSTR& bstrUser ,
  1410. /*[out]*/ DWORD *pdwAllowedIdentity )
  1411. {
  1412. __MPC_FUNC_ENTRY( COMMONID, "MPC::GetCallerPrincipal" );
  1413. HRESULT hr;
  1414. DWORD dwRes;
  1415. LPWSTR szUserSid = NULL;
  1416. PTOKEN_USER ptkUser = NULL;
  1417. PTOKEN_GROUPS ptkGroups = NULL;
  1418. DWORD dwSize;
  1419. MPC::Impersonation imp;
  1420. if(fImpersonate)
  1421. {
  1422. __MPC_EXIT_IF_METHOD_FAILS(hr, imp.Initialize( TOKEN_QUERY ));
  1423. }
  1424. else
  1425. {
  1426. HANDLE hToken;
  1427. //
  1428. // First try the token attached to the thread, then the one attached to the process.
  1429. //
  1430. if(::OpenThreadToken( ::GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken ) == FALSE)
  1431. {
  1432. if((dwRes = ::GetLastError()) != ERROR_NO_TOKEN)
  1433. {
  1434. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes);
  1435. }
  1436. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::OpenProcessToken( ::GetCurrentProcess(), TOKEN_QUERY, &hToken ));
  1437. }
  1438. imp.Attach( hToken );
  1439. }
  1440. //
  1441. // Get caller's credentials.
  1442. //
  1443. dwSize = 0;
  1444. ::GetTokenInformation( (HANDLE)imp, TokenUser, NULL, 0, &dwSize );
  1445. if((dwRes = ::GetLastError()) != ERROR_INSUFFICIENT_BUFFER)
  1446. {
  1447. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes);
  1448. }
  1449. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::SecurityDescriptor::AllocateMemory( (void*&)ptkUser, dwSize ));
  1450. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetTokenInformation( (HANDLE)imp, TokenUser, ptkUser, dwSize, &dwSize ));
  1451. //
  1452. // Convert to string.
  1453. //
  1454. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::ConvertSidToStringSidW( ptkUser->User.Sid, &szUserSid ));
  1455. //
  1456. // Verify identity, if requested.
  1457. //
  1458. if(pdwAllowedIdentity)
  1459. {
  1460. DWORD dwAllowedIdentity = 0;
  1461. if(::EqualSid( ptkUser->User.Sid, (PSID)& MPC::SecurityDescriptor::s_SystemSid )) dwAllowedIdentity |= IDENTITY_SYSTEM;
  1462. if(::EqualSid( ptkUser->User.Sid, (PSID)&(SID&)MPC::SecurityDescriptor::s_AdminSid )) dwAllowedIdentity |= IDENTITY_ADMIN;
  1463. //
  1464. // Get caller's groups.
  1465. //
  1466. dwSize = 0;
  1467. ::GetTokenInformation( (HANDLE)imp, TokenGroups, NULL, 0, &dwSize );
  1468. if((dwRes = ::GetLastError()) != ERROR_INSUFFICIENT_BUFFER)
  1469. {
  1470. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes);
  1471. }
  1472. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::SecurityDescriptor::AllocateMemory( (void*&)ptkGroups, dwSize ));
  1473. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetTokenInformation( (HANDLE)imp, TokenGroups, ptkGroups, dwSize, &dwSize ));
  1474. for(DWORD i=0; i<ptkGroups->GroupCount; i++)
  1475. {
  1476. SID_AND_ATTRIBUTES* grp = &ptkGroups->Groups[i];
  1477. if(grp->Attributes & SE_GROUP_ENABLED)
  1478. {
  1479. if(::EqualSid( grp->Sid, (PSID)&(SID&)MPC::SecurityDescriptor::s_Alias_AdminsSid )) dwAllowedIdentity |= IDENTITY_ADMINS;
  1480. if(::EqualSid( grp->Sid, (PSID)&(SID&)MPC::SecurityDescriptor::s_Alias_PowerUsersSid )) dwAllowedIdentity |= IDENTITY_POWERUSERS;
  1481. if(::EqualSid( grp->Sid, (PSID)&(SID&)MPC::SecurityDescriptor::s_Alias_UsersSid )) dwAllowedIdentity |= IDENTITY_USERS;
  1482. if(::EqualSid( grp->Sid, (PSID)&(SID&)MPC::SecurityDescriptor::s_Alias_GuestsSid )) dwAllowedIdentity |= IDENTITY_GUESTS;
  1483. }
  1484. }
  1485. *pdwAllowedIdentity = dwAllowedIdentity;
  1486. }
  1487. bstrUser = szUserSid;
  1488. hr = S_OK;
  1489. __MPC_FUNC_CLEANUP;
  1490. if(szUserSid) ::LocalFree( szUserSid );
  1491. MPC::SecurityDescriptor::ReleaseMemory( (void*&)ptkUser );
  1492. MPC::SecurityDescriptor::ReleaseMemory( (void*&)ptkGroups );
  1493. __MPC_FUNC_EXIT(hr);
  1494. }
  1495. ////////////////////////////////////////////////////////////////////////////////
  1496. HRESULT MPC::CheckCallerAgainstPrincipal( /*[in ]*/ bool fImpersonate ,
  1497. /*[out]*/ BSTR bstrUser ,
  1498. /*[in ]*/ DWORD dwAllowedIdentity )
  1499. {
  1500. __MPC_FUNC_ENTRY( COMMONID, "MPC::CheckCallerAgainstPrincipal" );
  1501. HRESULT hr;
  1502. CComBSTR bstrRealUser;
  1503. DWORD dwTokenIdentity;
  1504. __MPC_EXIT_IF_METHOD_FAILS(hr, GetCallerPrincipal( fImpersonate, bstrRealUser, &dwTokenIdentity ));
  1505. if(!MPC::StrICmp( bstrRealUser, bstrUser ))
  1506. {
  1507. //
  1508. // Same user, exit.
  1509. //
  1510. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  1511. }
  1512. if((dwTokenIdentity & dwAllowedIdentity) != 0)
  1513. {
  1514. //
  1515. // Not same user, but an authorized one, exit.
  1516. //
  1517. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  1518. }
  1519. hr = E_ACCESSDENIED;
  1520. __MPC_FUNC_CLEANUP;
  1521. __MPC_FUNC_EXIT(hr);
  1522. }
  1523. ////////////////////////////////////////////////////////////////////////////////
  1524. ////////////////////////////////////////////////////////////////////////////////
  1525. ////////////////////////////////////////////////////////////////////////////////
  1526. HRESULT MPC::GetInterfaceSecurity( /*[in ]*/ IUnknown* pUnk ,
  1527. /*[out]*/ DWORD *pAuthnSvc ,
  1528. /*[out]*/ DWORD *pAuthzSvc ,
  1529. /*[out]*/ OLECHAR* *pServerPrincName ,
  1530. /*[out]*/ DWORD *pAuthnLevel ,
  1531. /*[out]*/ DWORD *pImpLevel ,
  1532. /*[out]*/ RPC_AUTH_IDENTITY_HANDLE *pAuthInfo ,
  1533. /*[out]*/ DWORD *pCapabilities )
  1534. {
  1535. __MPC_FUNC_ENTRY( COMMONID, "MPC::GetInterfaceSecurity" );
  1536. HRESULT hr;
  1537. CComPtr<IClientSecurity> pBlanket;
  1538. __MPC_EXIT_IF_METHOD_FAILS(hr, pUnk->QueryInterface( IID_IClientSecurity, (void**)&pBlanket ));
  1539. __MPC_EXIT_IF_METHOD_FAILS(hr, pBlanket->QueryBlanket( pUnk ,
  1540. pAuthnSvc ,
  1541. pAuthzSvc ,
  1542. pServerPrincName ,
  1543. pAuthnLevel ,
  1544. pImpLevel ,
  1545. pAuthInfo ,
  1546. pCapabilities ));
  1547. hr = S_OK;
  1548. __MPC_FUNC_CLEANUP;
  1549. __MPC_FUNC_EXIT(hr);
  1550. }
  1551. HRESULT MPC::SetInterfaceSecurity( /*[in]*/ IUnknown* pUnk ,
  1552. /*[in]*/ DWORD *pAuthnSvc ,
  1553. /*[in]*/ DWORD *pAuthzSvc ,
  1554. /*[in]*/ OLECHAR* pServerPrincName ,
  1555. /*[in]*/ DWORD *pAuthnLevel ,
  1556. /*[in]*/ DWORD *pImpLevel ,
  1557. /*[in]*/ RPC_AUTH_IDENTITY_HANDLE *pAuthInfo ,
  1558. /*[in]*/ DWORD *pCapabilities )
  1559. {
  1560. __MPC_FUNC_ENTRY( COMMONID, "MPC::SetInterfaceSecurity" );
  1561. HRESULT hr;
  1562. CComPtr<IClientSecurity> pBlanket;
  1563. DWORD AuthnSvc;
  1564. DWORD AuthzSvc;
  1565. OLECHAR* ServerPrincName = NULL;
  1566. DWORD AuthnLevel;
  1567. DWORD ImpLevel;
  1568. DWORD Capabilities;
  1569. __MPC_EXIT_IF_METHOD_FAILS(hr, pUnk->QueryInterface( IID_IClientSecurity, (void**)&pBlanket ));
  1570. //
  1571. // First read the current settings.
  1572. //
  1573. __MPC_EXIT_IF_METHOD_FAILS(hr, pBlanket->QueryBlanket( pUnk ,
  1574. &AuthnSvc ,
  1575. &AuthzSvc ,
  1576. &ServerPrincName ,
  1577. &AuthnLevel ,
  1578. &ImpLevel ,
  1579. NULL ,
  1580. &Capabilities ));
  1581. //
  1582. // Update only some of them.
  1583. //
  1584. if(pAuthnSvc ) AuthnSvc = *pAuthnSvc;
  1585. if(pAuthzSvc ) AuthzSvc = *pAuthzSvc;
  1586. if(pAuthnLevel ) AuthnLevel = *pAuthnLevel;
  1587. if(pImpLevel ) ImpLevel = *pImpLevel;
  1588. if(pCapabilities ) Capabilities = *pCapabilities;
  1589. //
  1590. // Write back.
  1591. //
  1592. __MPC_EXIT_IF_METHOD_FAILS(hr, pBlanket->SetBlanket( pUnk ,
  1593. AuthnSvc ,
  1594. AuthzSvc ,
  1595. pServerPrincName ,
  1596. AuthnLevel ,
  1597. ImpLevel ,
  1598. pAuthInfo ,
  1599. Capabilities ));
  1600. hr = S_OK;
  1601. __MPC_FUNC_CLEANUP;
  1602. if(ServerPrincName) ::CoTaskMemFree( ServerPrincName );
  1603. __MPC_FUNC_EXIT(hr);
  1604. }
  1605. HRESULT MPC::SetInterfaceSecurity_ImpLevel( /*[in]*/ IUnknown* pUnk ,
  1606. /*[in]*/ DWORD ImpLevel )
  1607. {
  1608. return MPC::SetInterfaceSecurity( pUnk , /* IUnknown* pUnk */
  1609. NULL , /* DWORD *pAuthnSvc */
  1610. NULL , /* DWORD *pAuthzSvc */
  1611. NULL , /* OLECHAR* pServerPrincName */
  1612. NULL , /* DWORD *pAuthnLevel */
  1613. &ImpLevel , /* DWORD *pImpLevel */
  1614. NULL , /* RPC_AUTH_IDENTITY_HANDLE *pAuthInfo */
  1615. NULL ); /* DWORD *pCapabilities */
  1616. }