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.

622 lines
15 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: casec.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. /////////////////////////////////////////////////////////////////////
  11. // casec.cpp
  12. //
  13. // ISecurityInformation implementation for CA objects
  14. // and the new acl editor
  15. //
  16. // PURPOSE
  17. //
  18. //
  19. // DYNALOADED LIBRARIES
  20. //
  21. // HISTORY
  22. // 5-Nov-1998 petesk Copied template from privobsi.cpp sample.
  23. //
  24. /////////////////////////////////////////////////////////////////////
  25. #include <stdafx.h>
  26. #include <accctrl.h>
  27. #include <certca.h>
  28. #include <sddl.h>
  29. #include "certsrvd.h"
  30. #include "certacl.h"
  31. #define __dwFILE__ __dwFILE_CERTMMC_CASEC_CPP__
  32. //
  33. // defined in Security.cpp
  34. //
  35. // // define our generic mapping structure for our private objects //
  36. #define INHERIT_FULL (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE)
  37. GENERIC_MAPPING ObjMap =
  38. {
  39. ACTRL_CERTSRV_READ,
  40. DELETE | WRITE_DAC | WRITE_OWNER | ACTRL_DS_WRITE_PROP,
  41. 0,
  42. ACTRL_CERTSRV_MANAGE
  43. };
  44. //
  45. // DESCRIPTION OF ACCESS FLAG AFFECTS
  46. //
  47. // SI_ACCESS_GENERAL shows up on general properties page
  48. // SI_ACCESS_SPECIFIC shows up on advanced page
  49. // SI_ACCESS_CONTAINER shows on general page IF object is a container
  50. //
  51. SI_ACCESS g_siObjAccesses[] = {CERTSRV_SI_ACCESS_LIST};
  52. #define g_iObjDefAccess 3 // ENROLL enabled by default
  53. // The following array defines the inheritance types for my containers.
  54. SI_INHERIT_TYPE g_siObjInheritTypes[] =
  55. {
  56. &GUID_NULL, 0, MAKEINTRESOURCE(IDS_INH_NONE),
  57. };
  58. HRESULT
  59. LocalAllocString(LPWSTR* ppResult, LPCWSTR pString)
  60. {
  61. if (!ppResult || !pString)
  62. return E_INVALIDARG;
  63. *ppResult = (LPWSTR)LocalAlloc(LPTR, (lstrlen(pString) + 1) * sizeof(WCHAR));
  64. if (!*ppResult)
  65. return E_OUTOFMEMORY;
  66. lstrcpy(*ppResult, pString);
  67. return S_OK;
  68. }
  69. void
  70. LocalFreeString(LPWSTR* ppString)
  71. {
  72. if (ppString)
  73. {
  74. if (*ppString)
  75. LocalFree(*ppString);
  76. *ppString = NULL;
  77. }
  78. }
  79. class CCASecurityObject : public ISecurityInformation
  80. {
  81. protected:
  82. ULONG m_cRef;
  83. CertSvrCA * m_pSvrCA;
  84. // PSECURITY_DESCRIPTOR m_pSD;
  85. public:
  86. CCASecurityObject() : m_cRef(1)
  87. {
  88. m_pSvrCA = NULL;
  89. // m_pSD = NULL;
  90. }
  91. virtual ~CCASecurityObject();
  92. STDMETHOD(Initialize)(CertSvrCA *pCA);
  93. // IUnknown methods
  94. STDMETHOD(QueryInterface)(REFIID, LPVOID *);
  95. STDMETHOD_(ULONG, AddRef)();
  96. STDMETHOD_(ULONG, Release)();
  97. // ISecurityInformation methods
  98. STDMETHOD(GetObjectInformation)(PSI_OBJECT_INFO pObjectInfo);
  99. STDMETHOD(GetSecurity)(SECURITY_INFORMATION si,
  100. PSECURITY_DESCRIPTOR *ppSD,
  101. BOOL fDefault);
  102. STDMETHOD(SetSecurity)(SECURITY_INFORMATION si,
  103. PSECURITY_DESCRIPTOR pSD);
  104. STDMETHOD(GetAccessRights)(const GUID* pguidObjectType,
  105. DWORD dwFlags,
  106. PSI_ACCESS *ppAccess,
  107. ULONG *pcAccesses,
  108. ULONG *piDefaultAccess);
  109. STDMETHOD(MapGeneric)(const GUID *pguidObjectType,
  110. UCHAR *pAceFlags,
  111. ACCESS_MASK *pmask);
  112. STDMETHOD(GetInheritTypes)(PSI_INHERIT_TYPE *ppInheritTypes,
  113. ULONG *pcInheritTypes);
  114. STDMETHOD(PropertySheetPageCallback)(HWND hwnd,
  115. UINT uMsg,
  116. SI_PAGE_TYPE uPage);
  117. };
  118. ///////////////////////////////////////////////////////////////////////////////
  119. //
  120. // This is the entry point function called from our code that establishes
  121. // what the ACLUI interface is going to need to know.
  122. //
  123. //
  124. ///////////////////////////////////////////////////////////////////////////////
  125. extern "C"
  126. HRESULT
  127. CreateCASecurityInfo( CertSvrCA *pCA,
  128. LPSECURITYINFO *ppObjSI)
  129. {
  130. HRESULT hr;
  131. CCASecurityObject *psi;
  132. *ppObjSI = NULL;
  133. psi = new CCASecurityObject;
  134. if (!psi)
  135. return E_OUTOFMEMORY;
  136. hr = psi->Initialize(pCA);
  137. if (SUCCEEDED(hr))
  138. *ppObjSI = psi;
  139. else
  140. delete psi;
  141. return hr;
  142. }
  143. CCASecurityObject::~CCASecurityObject()
  144. {
  145. }
  146. STDMETHODIMP
  147. CCASecurityObject::Initialize(CertSvrCA *pCA)
  148. {
  149. m_pSvrCA = pCA;
  150. return S_OK;
  151. }
  152. ///////////////////////////////////////////////////////////
  153. //
  154. // IUnknown methods
  155. //
  156. ///////////////////////////////////////////////////////////
  157. STDMETHODIMP_(ULONG)
  158. CCASecurityObject::AddRef()
  159. {
  160. return ++m_cRef;
  161. }
  162. STDMETHODIMP_(ULONG)
  163. CCASecurityObject::Release()
  164. {
  165. if (--m_cRef == 0)
  166. {
  167. delete this;
  168. return 0;
  169. }
  170. return m_cRef;
  171. }
  172. STDMETHODIMP
  173. CCASecurityObject::QueryInterface(REFIID riid, LPVOID FAR* ppv)
  174. {
  175. if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ISecurityInformation))
  176. {
  177. *ppv = (LPSECURITYINFO)this;
  178. m_cRef++;
  179. return S_OK;
  180. }
  181. else
  182. {
  183. *ppv = NULL;
  184. return E_NOINTERFACE;
  185. }
  186. }
  187. ///////////////////////////////////////////////////////////
  188. //
  189. // ISecurityInformation methods
  190. //
  191. ///////////////////////////////////////////////////////////
  192. STDMETHODIMP
  193. CCASecurityObject::GetObjectInformation(PSI_OBJECT_INFO pObjectInfo)
  194. {
  195. if(pObjectInfo == NULL)
  196. {
  197. return E_POINTER;
  198. }
  199. if(m_pSvrCA == NULL)
  200. {
  201. return E_POINTER;
  202. }
  203. ZeroMemory(pObjectInfo, sizeof(SI_OBJECT_INFO));
  204. pObjectInfo->dwFlags = SI_EDIT_PERMS |
  205. SI_NO_TREE_APPLY |
  206. SI_EDIT_AUDITS |
  207. SI_NO_ACL_PROTECT |
  208. SI_NO_ADDITIONAL_PERMISSION;
  209. if(!m_pSvrCA->AccessAllowed(CA_ACCESS_ADMIN))
  210. pObjectInfo->dwFlags |= SI_READONLY;
  211. pObjectInfo->hInstance = g_hInstance;
  212. if(m_pSvrCA->m_pParentMachine)
  213. {
  214. pObjectInfo->pszServerName = const_cast<WCHAR *>((LPCTSTR)m_pSvrCA->m_pParentMachine->m_strMachineName);
  215. }
  216. pObjectInfo->pszObjectName = const_cast<WCHAR *>((LPCTSTR)m_pSvrCA->m_strCommonName);
  217. return S_OK;
  218. }
  219. STDMETHODIMP
  220. CCASecurityObject::GetSecurity(SECURITY_INFORMATION si,
  221. PSECURITY_DESCRIPTOR *ppSD,
  222. BOOL fDefault)
  223. {
  224. HRESULT hr = S_OK;
  225. // DWORD dwLength = 0;
  226. DWORD dwErr = ERROR_SUCCESS;
  227. // PSECURITY_DESCRIPTOR pSD = NULL;
  228. SECURITY_DESCRIPTOR_CONTROL Control = SE_DACL_PROTECTED;
  229. DWORD dwRevision = 0;
  230. *ppSD = NULL;
  231. if (fDefault||
  232. DACL_SECURITY_INFORMATION!=si)
  233. return E_NOTIMPL;
  234. //
  235. // Assume that required privileges have already been enabled
  236. //
  237. ICertAdminD2 *pICertAdminD = NULL;
  238. DWORD dwServerVersion = 0; // 0 required by myOpenAdminDComConnection
  239. WCHAR const *pwszAuthority;
  240. CERTTRANSBLOB ctbSD;
  241. ZeroMemory(&ctbSD, sizeof(CERTTRANSBLOB));
  242. if(m_pSvrCA)
  243. {
  244. hr = myOpenAdminDComConnection(
  245. m_pSvrCA->m_bstrConfig,
  246. &pwszAuthority,
  247. NULL,
  248. &dwServerVersion,
  249. &pICertAdminD);
  250. _JumpIfError(hr, error, "myOpenAdminDComConnection");
  251. if (2 > dwServerVersion)
  252. {
  253. hr = RPC_E_VERSION_MISMATCH;
  254. _JumpError(hr, error, "old server");
  255. }
  256. __try
  257. {
  258. hr = pICertAdminD->GetCASecurity(
  259. pwszAuthority,
  260. &ctbSD);
  261. }
  262. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  263. {
  264. }
  265. _JumpIfError(hr, error, "pICertAdminD->GetCASecurity");
  266. myRegisterMemAlloc(ctbSD.pb, ctbSD.cb, CSM_COTASKALLOC);
  267. // take the return
  268. *ppSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED, ctbSD.cb);
  269. if (NULL == *ppSD)
  270. {
  271. hr = E_OUTOFMEMORY;
  272. _JumpError(hr, error, "LocalAlloc");
  273. }
  274. MoveMemory(*ppSD, ctbSD.pb, ctbSD.cb);
  275. }
  276. if (NULL == *ppSD)
  277. {
  278. hr = E_UNEXPECTED;
  279. _JumpError(hr, error, "NULL secdescr");
  280. }
  281. if(GetSecurityDescriptorControl(*ppSD, &Control, &dwRevision))
  282. {
  283. Control &= SE_DACL_PROTECTED | SE_DACL_AUTO_INHERIT_REQ | SE_DACL_AUTO_INHERITED;
  284. SetSecurityDescriptorControl(*ppSD,
  285. SE_DACL_PROTECTED | SE_DACL_AUTO_INHERIT_REQ | SE_DACL_AUTO_INHERITED,
  286. Control);
  287. }
  288. #if DBG
  289. // dump *ppSD
  290. {
  291. LPWSTR szSecDescr = NULL;
  292. ConvertSecurityDescriptorToStringSecurityDescriptor(
  293. *ppSD,
  294. SDDL_REVISION_1,
  295. DACL_SECURITY_INFORMATION,
  296. &szSecDescr,
  297. NULL);
  298. if (szSecDescr)
  299. {
  300. myRegisterMemAlloc(szSecDescr, -1, CSM_LOCALALLOC);
  301. DBGPRINT((DBG_SS_CERTMMCI, "GetSecurity: %ws\n", szSecDescr));
  302. LocalFree(szSecDescr);
  303. }
  304. }
  305. #endif
  306. error:
  307. myCloseDComConnection((IUnknown **) &pICertAdminD, NULL);
  308. if (NULL != ctbSD.pb)
  309. {
  310. CoTaskMemFree(ctbSD.pb);
  311. }
  312. return hr;
  313. }
  314. STDMETHODIMP
  315. CCASecurityObject::SetSecurity(SECURITY_INFORMATION si,
  316. PSECURITY_DESCRIPTOR pSD)
  317. {
  318. HRESULT hr = S_OK;
  319. DWORD dwErr = ERROR_SUCCESS;
  320. HANDLE hClientToken = NULL;
  321. HANDLE hHandle = NULL;
  322. HKEY hConfigKey = NULL;
  323. SECURITY_DESCRIPTOR_CONTROL Control = SE_DACL_PROTECTED;
  324. DWORD dwRevision = 0;
  325. ICertAdminD2 *pICertAdminD = NULL;
  326. DWORD dwServerVersion = 0;
  327. CERTTRANSBLOB ctbSD;
  328. WCHAR const *pwszAuthority;
  329. DWORD dwSize;
  330. PSECURITY_DESCRIPTOR pSDSelfRel = NULL;
  331. if (DACL_SECURITY_INFORMATION!=si)
  332. return E_NOTIMPL;
  333. hHandle = GetCurrentThread();
  334. if (NULL == hHandle)
  335. {
  336. hr = myHLastError();
  337. }
  338. else
  339. {
  340. if (!OpenThreadToken(hHandle,
  341. TOKEN_QUERY,
  342. TRUE, // open as self
  343. &hClientToken))
  344. {
  345. hr = myHLastError();
  346. CloseHandle(hHandle);
  347. hHandle = NULL;
  348. }
  349. }
  350. if(hr != S_OK)
  351. {
  352. hHandle = GetCurrentProcess();
  353. if (NULL == hHandle)
  354. {
  355. hr = myHLastError();
  356. }
  357. else
  358. {
  359. HANDLE hProcessToken = NULL;
  360. hr = S_OK;
  361. if (!OpenProcessToken(hHandle,
  362. TOKEN_DUPLICATE,
  363. &hProcessToken))
  364. {
  365. hr = myHLastError();
  366. CloseHandle(hHandle);
  367. hHandle = NULL;
  368. }
  369. else
  370. {
  371. if(!DuplicateToken(hProcessToken,
  372. SecurityImpersonation,
  373. &hClientToken))
  374. {
  375. hr = myHLastError();
  376. CloseHandle(hHandle);
  377. hHandle = NULL;
  378. }
  379. CloseHandle(hProcessToken);
  380. }
  381. }
  382. }
  383. if(hr != S_OK)
  384. {
  385. goto error;
  386. }
  387. if(si & DACL_SECURITY_INFORMATION)
  388. {
  389. if(GetSecurityDescriptorControl(pSD, &Control, &dwRevision))
  390. {
  391. Control &= SE_DACL_PROTECTED | SE_DACL_AUTO_INHERIT_REQ | SE_DACL_AUTO_INHERITED;
  392. SetSecurityDescriptorControl(pSD,
  393. SE_DACL_PROTECTED | SE_DACL_AUTO_INHERIT_REQ | SE_DACL_AUTO_INHERITED,
  394. Control);
  395. }
  396. }
  397. dwSize = GetSecurityDescriptorLength(pSD);
  398. pSDSelfRel = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED, dwSize);
  399. if(NULL == pSDSelfRel)
  400. {
  401. hr = E_OUTOFMEMORY;
  402. _JumpError(hr, error, "LocalAlloc");
  403. }
  404. if(!MakeSelfRelativeSD(pSD, pSDSelfRel, &dwSize))
  405. {
  406. LocalFree(pSDSelfRel);
  407. pSDSelfRel = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED, dwSize);
  408. if(NULL == pSDSelfRel)
  409. {
  410. hr = E_OUTOFMEMORY;
  411. _JumpError(hr, error, "LocalAlloc");
  412. }
  413. if(!MakeSelfRelativeSD(pSD, pSDSelfRel, &dwSize))
  414. {
  415. hr = myHLastError();
  416. _JumpError(hr, error, "LocalAlloc");
  417. }
  418. }
  419. hr = myOpenAdminDComConnection(
  420. m_pSvrCA->m_bstrConfig,
  421. &pwszAuthority,
  422. NULL,
  423. &dwServerVersion,
  424. &pICertAdminD);
  425. _JumpIfError(hr, error, "myOpenAdminDComConnection");
  426. if (2 > dwServerVersion)
  427. {
  428. hr = RPC_E_VERSION_MISMATCH;
  429. _JumpError(hr, error, "old server");
  430. }
  431. __try
  432. {
  433. ctbSD.cb = GetSecurityDescriptorLength(pSDSelfRel);
  434. ctbSD.pb = (BYTE*)pSDSelfRel;
  435. hr = pICertAdminD->SetCASecurity(
  436. pwszAuthority,
  437. &ctbSD);
  438. if(hr == HRESULT_FROM_WIN32(ERROR_CAN_NOT_COMPLETE))
  439. {
  440. // Attempt to fix enrollment object, see bug# 193388
  441. m_pSvrCA->FixEnrollmentObject();
  442. // try again
  443. hr = pICertAdminD->SetCASecurity(
  444. pwszAuthority,
  445. &ctbSD);
  446. }
  447. }
  448. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  449. {
  450. }
  451. _JumpIfError(hr, error, "pICertAdminD->SetCASecurity");
  452. #if DBG
  453. // dump m_pSD
  454. {
  455. LPWSTR szSecDescr = NULL;
  456. ConvertSecurityDescriptorToStringSecurityDescriptor(
  457. pSD,
  458. SDDL_REVISION_1,
  459. DACL_SECURITY_INFORMATION,
  460. &szSecDescr,
  461. NULL);
  462. if (szSecDescr)
  463. {
  464. myRegisterMemAlloc(szSecDescr, -1, CSM_LOCALALLOC);
  465. DBGPRINT((DBG_SS_CERTMMCI, "SetSecurity: %ws\n", szSecDescr));
  466. LocalFree(szSecDescr);
  467. }
  468. }
  469. #endif
  470. error:
  471. myCloseDComConnection((IUnknown **) &pICertAdminD, NULL);
  472. if(hClientToken)
  473. {
  474. CloseHandle(hClientToken);
  475. }
  476. if(hHandle)
  477. {
  478. CloseHandle(hHandle);
  479. }
  480. if(NULL != pSDSelfRel)
  481. {
  482. LocalFree(pSDSelfRel);
  483. }
  484. return hr;
  485. }
  486. STDMETHODIMP
  487. CCASecurityObject::GetAccessRights(const GUID* /*pguidObjectType*/,
  488. DWORD /*dwFlags*/,
  489. PSI_ACCESS *ppAccesses,
  490. ULONG *pcAccesses,
  491. ULONG *piDefaultAccess)
  492. {
  493. *ppAccesses = g_siObjAccesses;
  494. *pcAccesses = sizeof(g_siObjAccesses)/sizeof(g_siObjAccesses[0]);
  495. *piDefaultAccess = g_iObjDefAccess;
  496. return S_OK;
  497. }
  498. STDMETHODIMP
  499. CCASecurityObject::MapGeneric(const GUID* /*pguidObjectType*/,
  500. UCHAR * /*pAceFlags*/,
  501. ACCESS_MASK *pmask)
  502. {
  503. MapGenericMask(pmask, &ObjMap);
  504. return S_OK;
  505. }
  506. STDMETHODIMP
  507. CCASecurityObject::GetInheritTypes(PSI_INHERIT_TYPE *ppInheritTypes,
  508. ULONG *pcInheritTypes)
  509. {
  510. *ppInheritTypes = g_siObjInheritTypes;
  511. *pcInheritTypes = sizeof(g_siObjInheritTypes)/sizeof(g_siObjInheritTypes[0]);
  512. return S_OK;
  513. }
  514. STDMETHODIMP
  515. CCASecurityObject::PropertySheetPageCallback(HWND /*hwnd*/,
  516. UINT /*uMsg*/,
  517. SI_PAGE_TYPE /*uPage*/)
  518. {
  519. return S_OK;
  520. }