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.

605 lines
17 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998-2001
  6. //
  7. // File: SecurityPropertyPage.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. // 6-Mar-2000 bryanwal Modified to support cert templates
  24. //
  25. /////////////////////////////////////////////////////////////////////
  26. #include <stdafx.h>
  27. #include <accctrl.h>
  28. //#include <certca.h>
  29. #include <sddl.h>
  30. #include "CertTemplate.h"
  31. // Important, keep enroll GUID in sync with string define in certacl.h
  32. const GUID GUID_ENROLL = { /* 0e10c968-78fb-11d2-90d4-00c04f79dc55 */
  33. 0x0e10c968,
  34. 0x78fb,
  35. 0x11d2,
  36. {0x90, 0xd4, 0x00, 0xc0, 0x4f, 0x79, 0xdc, 0x55} };
  37. const GUID GUID_AUTOENROLL = { /* a05b8cc2-17bc-4802-a710-e7c15ab866a2 */
  38. 0xa05b8cc2,
  39. 0x17bc,
  40. 0x4802,
  41. {0xa7, 0x10, 0xe7, 0xc1, 0x5a, 0xb8, 0x66, 0xa2} };
  42. //
  43. // defined in Security.cpp
  44. //
  45. // // define our generic mapping structure for our private objects //
  46. #define INHERIT_FULL (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE)
  47. #define ACTRL_CERTSRV_ENROLL (ACTRL_DS_READ_PROP | \
  48. ACTRL_DS_WRITE_PROP | \
  49. ACTRL_DS_CONTROL_ACCESS)
  50. #define ACTRL_CERTSRV_MANAGE (ACTRL_DS_READ_PROP | \
  51. ACTRL_DS_WRITE_PROP | \
  52. READ_CONTROL | \
  53. DELETE | \
  54. WRITE_DAC | \
  55. WRITE_OWNER | \
  56. ACTRL_DS_CONTROL_ACCESS | \
  57. ACTRL_DS_CREATE_CHILD | \
  58. ACTRL_DS_DELETE_CHILD | \
  59. ACTRL_DS_LIST | \
  60. ACTRL_DS_SELF | \
  61. ACTRL_DS_DELETE_TREE | \
  62. ACTRL_DS_LIST_OBJECT)
  63. #define ACTRL_CERTSRV_READ ( READ_CONTROL | \
  64. ACTRL_DS_READ_PROP | \
  65. ACTRL_DS_LIST | \
  66. ACTRL_DS_LIST_OBJECT )
  67. #define ACTRL_CERTSRV_WRITE ( WRITE_DAC | \
  68. WRITE_OWNER | \
  69. ACTRL_DS_WRITE_PROP )
  70. GENERIC_MAPPING ObjMap =
  71. {
  72. ACTRL_CERTSRV_READ,
  73. DELETE | WRITE_DAC | WRITE_OWNER | ACTRL_DS_WRITE_PROP,
  74. 0,
  75. ACTRL_CERTSRV_MANAGE
  76. };
  77. //
  78. // DESCRIPTION OF ACCESS FLAG AFFECTS
  79. //
  80. // SI_ACCESS_GENERAL shows up on general properties page
  81. // SI_ACCESS_SPECIFIC shows up on advanced page
  82. // SI_ACCESS_CONTAINER shows on general page IF object is a container
  83. //
  84. SI_ACCESS g_siV1ObjAccesses[] =
  85. {
  86. { &GUID_NULL,
  87. ACTRL_CERTSRV_MANAGE,
  88. MAKEINTRESOURCE(IDS_ACTRL_CERTSRV_MANAGE),
  89. SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC },
  90. { &GUID_NULL,
  91. ACTRL_CERTSRV_READ,
  92. MAKEINTRESOURCE(IDS_ACTRL_CERTSRV_READ),
  93. SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC },
  94. { &GUID_NULL,
  95. ACTRL_CERTSRV_WRITE,
  96. MAKEINTRESOURCE(IDS_ACTRL_CERTSRV_WRITE),
  97. SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC },
  98. { &GUID_ENROLL,
  99. ACTRL_CERTSRV_ENROLL,
  100. MAKEINTRESOURCE(IDS_ACTRL_ENROLL),
  101. SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }
  102. };
  103. SI_ACCESS g_siV2ObjAccesses[] =
  104. {
  105. { &GUID_NULL,
  106. ACTRL_CERTSRV_MANAGE,
  107. MAKEINTRESOURCE(IDS_ACTRL_CERTSRV_MANAGE),
  108. SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC },
  109. { &GUID_NULL,
  110. ACTRL_CERTSRV_READ,
  111. MAKEINTRESOURCE(IDS_ACTRL_CERTSRV_READ),
  112. SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC },
  113. { &GUID_NULL,
  114. ACTRL_CERTSRV_WRITE,
  115. MAKEINTRESOURCE(IDS_ACTRL_CERTSRV_WRITE),
  116. SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC },
  117. { &GUID_ENROLL,
  118. ACTRL_CERTSRV_ENROLL,
  119. MAKEINTRESOURCE(IDS_ACTRL_ENROLL),
  120. SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC },
  121. { &GUID_AUTOENROLL,
  122. ACTRL_CERTSRV_ENROLL,
  123. MAKEINTRESOURCE(IDS_ACTRL_AUTOENROLL),
  124. SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }
  125. };
  126. #define g_iObjDefAccess 1 // DS_GENERIC_READ
  127. // The following array defines the inheritance types for my containers.
  128. SI_INHERIT_TYPE g_siObjInheritTypes[] =
  129. {
  130. &GUID_NULL, 0, MAKEINTRESOURCE(IDS_INH_NONE),
  131. };
  132. HRESULT
  133. LocalAllocString(LPWSTR* ppResult, LPCWSTR pString)
  134. {
  135. if (!ppResult || !pString)
  136. return E_INVALIDARG;
  137. *ppResult = (LPWSTR)LocalAlloc(LPTR, (lstrlen(pString) + 1) * sizeof(WCHAR));
  138. if (!*ppResult)
  139. return E_OUTOFMEMORY;
  140. lstrcpy(*ppResult, pString);
  141. return S_OK;
  142. }
  143. void
  144. LocalFreeString(LPWSTR* ppString)
  145. {
  146. if (ppString)
  147. {
  148. if (*ppString)
  149. LocalFree(*ppString);
  150. *ppString = NULL;
  151. }
  152. }
  153. class CCertTemplateSecurityObject : public ISecurityInformation
  154. {
  155. protected:
  156. ULONG m_cRef;
  157. CCertTemplate * m_pCertTemplate;
  158. PSECURITY_DESCRIPTOR m_pSD;
  159. public:
  160. CCertTemplateSecurityObject() : m_cRef(1),
  161. m_pCertTemplate (0),
  162. m_pSD (0)
  163. {
  164. }
  165. virtual ~CCertTemplateSecurityObject();
  166. STDMETHOD(Initialize)(CCertTemplate *pCertTemplate);
  167. // IUnknown methods
  168. STDMETHOD(QueryInterface)(REFIID, LPVOID *);
  169. STDMETHOD_(ULONG, AddRef)();
  170. STDMETHOD_(ULONG, Release)();
  171. // ISecurityInformation methods
  172. STDMETHOD(GetObjectInformation)(PSI_OBJECT_INFO pObjectInfo);
  173. STDMETHOD(GetSecurity)(SECURITY_INFORMATION si,
  174. PSECURITY_DESCRIPTOR *ppSD,
  175. BOOL fDefault);
  176. STDMETHOD(SetSecurity)(SECURITY_INFORMATION si,
  177. PSECURITY_DESCRIPTOR pSD);
  178. STDMETHOD(GetAccessRights)(const GUID* pguidObjectType,
  179. DWORD dwFlags,
  180. PSI_ACCESS *ppAccess,
  181. ULONG *pcAccesses,
  182. ULONG *piDefaultAccess);
  183. STDMETHOD(MapGeneric)(const GUID *pguidObjectType,
  184. UCHAR *pAceFlags,
  185. ACCESS_MASK *pmask);
  186. STDMETHOD(GetInheritTypes)(PSI_INHERIT_TYPE *ppInheritTypes,
  187. ULONG *pcInheritTypes);
  188. STDMETHOD(PropertySheetPageCallback)(HWND hwnd,
  189. UINT uMsg,
  190. SI_PAGE_TYPE uPage);
  191. };
  192. ///////////////////////////////////////////////////////////////////////////////
  193. //
  194. // This is the entry point function called from our code that establishes
  195. // what the ACLUI interface is going to need to know.
  196. //
  197. //
  198. ///////////////////////////////////////////////////////////////////////////////
  199. HRESULT CreateCertTemplateSecurityInfo (
  200. CCertTemplate *pCertTemplate,
  201. LPSECURITYINFO *ppObjSI)
  202. {
  203. _TRACE (1, L"Entering CreateCertTemplateSecurityInfo\n");
  204. ASSERT (pCertTemplate && ppObjSI);
  205. if ( !pCertTemplate || !ppObjSI )
  206. return E_POINTER;
  207. HRESULT hr = S_OK;
  208. CCertTemplateSecurityObject *psi = new CCertTemplateSecurityObject;
  209. if ( psi)
  210. {
  211. *ppObjSI = NULL;
  212. hr = psi->Initialize (pCertTemplate);
  213. if ( SUCCEEDED (hr) )
  214. *ppObjSI = psi;
  215. else
  216. delete psi;
  217. }
  218. else
  219. hr = E_OUTOFMEMORY;;
  220. _TRACE (-1, L"Leaving CreateCertTemplateSecurityInfo: 0x%x\n", hr);
  221. return hr;
  222. }
  223. CCertTemplateSecurityObject::~CCertTemplateSecurityObject()
  224. {
  225. if ( m_pSD )
  226. {
  227. LocalFree (m_pSD);
  228. }
  229. if ( m_pCertTemplate )
  230. m_pCertTemplate->Release ();
  231. }
  232. STDMETHODIMP
  233. CCertTemplateSecurityObject::Initialize(CCertTemplate *pCertTemplate)
  234. {
  235. _TRACE (1, L"Entering CCertTemplateSecurityObject::Initialize\n");
  236. HRESULT hr = S_OK;
  237. if ( pCertTemplate )
  238. {
  239. m_pCertTemplate = pCertTemplate;
  240. m_pCertTemplate->AddRef ();
  241. hr = pCertTemplate->GetSecurity (&m_pSD);
  242. }
  243. else
  244. hr = E_POINTER;
  245. _TRACE (-1, L"Leaving CCertTemplateSecurityObject::Initialize: 0x%x\n", hr);
  246. return hr;
  247. }
  248. ///////////////////////////////////////////////////////////
  249. //
  250. // IUnknown methods
  251. //
  252. ///////////////////////////////////////////////////////////
  253. STDMETHODIMP_(ULONG)
  254. CCertTemplateSecurityObject::AddRef()
  255. {
  256. return ++m_cRef;
  257. }
  258. STDMETHODIMP_(ULONG)
  259. CCertTemplateSecurityObject::Release()
  260. {
  261. if (--m_cRef == 0)
  262. {
  263. delete this;
  264. return 0;
  265. }
  266. return m_cRef;
  267. }
  268. STDMETHODIMP
  269. CCertTemplateSecurityObject::QueryInterface(REFIID riid, LPVOID FAR* ppv)
  270. {
  271. if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ISecurityInformation))
  272. {
  273. *ppv = (LPSECURITYINFO)this;
  274. m_cRef++;
  275. return S_OK;
  276. }
  277. else
  278. {
  279. *ppv = NULL;
  280. return E_NOINTERFACE;
  281. }
  282. }
  283. ///////////////////////////////////////////////////////////
  284. //
  285. // ISecurityInformation methods
  286. //
  287. ///////////////////////////////////////////////////////////
  288. STDMETHODIMP
  289. CCertTemplateSecurityObject::GetObjectInformation(PSI_OBJECT_INFO pObjectInfo)
  290. {
  291. if ( pObjectInfo == NULL )
  292. {
  293. return E_POINTER;
  294. }
  295. if ( m_pCertTemplate == NULL )
  296. {
  297. return E_POINTER;
  298. }
  299. ZeroMemory(pObjectInfo, sizeof(SI_OBJECT_INFO));
  300. pObjectInfo->dwFlags = SI_EDIT_ALL | SI_NO_ACL_PROTECT | SI_ADVANCED | SI_NO_ADDITIONAL_PERMISSION;
  301. if ( m_pCertTemplate->ReadOnly () )
  302. pObjectInfo->dwFlags |= SI_READONLY;
  303. AFX_MANAGE_STATE (AfxGetStaticModuleState ());
  304. pObjectInfo->hInstance = AfxGetResourceHandle (); //AfxGetInstanceHandle ();
  305. // if(m_pCertTemplate->m_pParentMachine)
  306. // {
  307. // pObjectInfo->pszServerName = const_cast<WCHAR *>((LPCTSTR)m_pCertTemplate->m_pParentMachine->m_strMachineName);
  308. // }
  309. pObjectInfo->pszObjectName = const_cast<WCHAR *>((LPCTSTR)m_pCertTemplate->GetLDAPPath ());
  310. //pObjectInfo->pszPageTitle = NULL; // already zeroed above
  311. return S_OK;
  312. }
  313. STDMETHODIMP
  314. CCertTemplateSecurityObject::GetSecurity(SECURITY_INFORMATION si,
  315. PSECURITY_DESCRIPTOR *ppSD,
  316. BOOL fDefault)
  317. {
  318. _TRACE (1, L"Entering CCertTemplateSecurityObject::GetSecurity\n");
  319. HRESULT hr = S_OK;
  320. DWORD dwLength = 0;
  321. SECURITY_DESCRIPTOR_CONTROL Control = SE_DACL_PROTECTED;
  322. DWORD dwRevision = 0;
  323. *ppSD = NULL;
  324. if (fDefault)
  325. return E_NOTIMPL;
  326. //
  327. // Assume that required privileges have already been enabled
  328. //
  329. hr = S_OK;
  330. // find out out much to allocate
  331. if ( !GetPrivateObjectSecurity(m_pSD, si, NULL, 0, &dwLength) )
  332. {
  333. hr = HRESULT_FROM_WIN32 (GetLastError ());
  334. if ( hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER) && dwLength )
  335. {
  336. hr = S_OK;
  337. // allocate and
  338. *ppSD = LocalAlloc(LPTR, dwLength);
  339. if (*ppSD )
  340. {
  341. // retrieve
  342. if ( GetPrivateObjectSecurity (m_pSD, si, *ppSD, dwLength, &dwLength) )
  343. {
  344. if ( GetSecurityDescriptorControl(m_pSD, &Control, &dwRevision))
  345. {
  346. Control &= SE_DACL_PROTECTED | SE_DACL_AUTO_INHERIT_REQ | SE_DACL_AUTO_INHERITED;
  347. SetSecurityDescriptorControl (*ppSD,
  348. SE_DACL_PROTECTED | SE_DACL_AUTO_INHERIT_REQ | SE_DACL_AUTO_INHERITED,
  349. Control);
  350. }
  351. else
  352. {
  353. hr = HRESULT_FROM_WIN32 (GetLastError ());
  354. _TRACE (0, L"GetSecurityDescriptorControl failed: 0x%x\n", hr);
  355. }
  356. }
  357. else
  358. {
  359. _TRACE (0, L"GetPrivateObjectSecurity failed: 0x%x\n", hr);
  360. hr = GetLastError();
  361. LocalFree(*ppSD);
  362. *ppSD = NULL;
  363. }
  364. }
  365. else
  366. hr = E_OUTOFMEMORY;
  367. }
  368. else if ( FAILED (hr) )
  369. {
  370. _TRACE (0, L"GetPrivateObjectSecurity failed: 0x%x\n", hr);
  371. }
  372. }
  373. else
  374. {
  375. hr = HRESULT_FROM_WIN32 (GetLastError ());
  376. }
  377. _TRACE (-1, L"Leaving CCertTemplateSecurityObject::GetSecurity: 0x%x\n", hr);
  378. return hr;
  379. }
  380. STDMETHODIMP
  381. CCertTemplateSecurityObject::SetSecurity(SECURITY_INFORMATION si,
  382. PSECURITY_DESCRIPTOR pSD)
  383. {
  384. HRESULT hr = S_OK;
  385. HANDLE hClientToken = NULL;
  386. HANDLE hHandle = NULL;
  387. SECURITY_DESCRIPTOR_CONTROL Control = SE_DACL_PROTECTED;
  388. DWORD dwRevision = 0;
  389. hHandle = GetCurrentThread();
  390. if (NULL == hHandle)
  391. {
  392. hr = HRESULT_FROM_WIN32 (GetLastError());
  393. }
  394. else
  395. {
  396. if (!OpenThreadToken(hHandle,
  397. TOKEN_QUERY,
  398. TRUE, // open as self
  399. &hClientToken))
  400. {
  401. hr = HRESULT_FROM_WIN32 (GetLastError());
  402. CloseHandle(hHandle);
  403. hHandle = NULL;
  404. }
  405. }
  406. if(hr != S_OK)
  407. {
  408. hHandle = GetCurrentProcess();
  409. if (NULL == hHandle)
  410. {
  411. hr = HRESULT_FROM_WIN32 (GetLastError());
  412. }
  413. else
  414. {
  415. HANDLE hProcessToken = NULL;
  416. hr = S_OK;
  417. if (!OpenProcessToken(hHandle,
  418. TOKEN_DUPLICATE,
  419. &hProcessToken))
  420. {
  421. hr = HRESULT_FROM_WIN32 (GetLastError());
  422. CloseHandle(hHandle);
  423. hHandle = NULL;
  424. }
  425. else
  426. {
  427. if(!DuplicateToken(hProcessToken,
  428. SecurityImpersonation,
  429. &hClientToken))
  430. {
  431. hr = HRESULT_FROM_WIN32 (GetLastError());
  432. CloseHandle(hHandle);
  433. hHandle = NULL;
  434. }
  435. CloseHandle(hProcessToken);
  436. }
  437. }
  438. }
  439. if ( SUCCEEDED (hr) )
  440. {
  441. //
  442. // Assume that required privileges have already been enabled
  443. //
  444. if ( SetPrivateObjectSecurityEx (si, pSD, &m_pSD, SEF_DACL_AUTO_INHERIT, &ObjMap, hClientToken) )
  445. {
  446. if ( si & DACL_SECURITY_INFORMATION )
  447. {
  448. if ( GetSecurityDescriptorControl (pSD, &Control, &dwRevision) )
  449. {
  450. Control &= SE_DACL_PROTECTED | SE_DACL_AUTO_INHERIT_REQ | SE_DACL_AUTO_INHERITED;
  451. SetSecurityDescriptorControl(m_pSD,
  452. SE_DACL_PROTECTED | SE_DACL_AUTO_INHERIT_REQ | SE_DACL_AUTO_INHERITED,
  453. Control);
  454. }
  455. }
  456. hr = m_pCertTemplate->SetSecurity (m_pSD);
  457. }
  458. else
  459. {
  460. hr = HRESULT_FROM_WIN32 (GetLastError());
  461. _TRACE (0, L"SetPrivateObjectSecurityEx () failed: 0x%x\n", hr);
  462. }
  463. }
  464. if ( hClientToken )
  465. {
  466. CloseHandle (hClientToken);
  467. }
  468. if ( hHandle )
  469. {
  470. CloseHandle (hHandle);
  471. }
  472. return hr;
  473. }
  474. STDMETHODIMP
  475. CCertTemplateSecurityObject::GetAccessRights(const GUID* /*pguidObjectType*/,
  476. DWORD /*dwFlags*/,
  477. PSI_ACCESS *ppAccesses,
  478. ULONG *pcAccesses,
  479. ULONG *piDefaultAccess)
  480. {
  481. if ( !ppAccesses || !pcAccesses || !piDefaultAccess )
  482. return E_POINTER;
  483. if ( 1 == m_pCertTemplate->GetType () )
  484. {
  485. *ppAccesses = g_siV1ObjAccesses;
  486. *pcAccesses = sizeof(g_siV1ObjAccesses)/sizeof(g_siV1ObjAccesses[0]);
  487. }
  488. else
  489. {
  490. *ppAccesses = g_siV2ObjAccesses;
  491. *pcAccesses = sizeof(g_siV2ObjAccesses)/sizeof(g_siV2ObjAccesses[0]);
  492. }
  493. *piDefaultAccess = g_iObjDefAccess;
  494. return S_OK;
  495. }
  496. STDMETHODIMP
  497. CCertTemplateSecurityObject::MapGeneric(const GUID* /*pguidObjectType*/,
  498. UCHAR * /*pAceFlags*/,
  499. ACCESS_MASK *pmask)
  500. {
  501. MapGenericMask(pmask, &ObjMap);
  502. return S_OK;
  503. }
  504. STDMETHODIMP
  505. CCertTemplateSecurityObject::GetInheritTypes(PSI_INHERIT_TYPE *ppInheritTypes,
  506. ULONG *pcInheritTypes)
  507. {
  508. *ppInheritTypes = g_siObjInheritTypes;
  509. *pcInheritTypes = sizeof(g_siObjInheritTypes)/sizeof(g_siObjInheritTypes[0]);
  510. return S_OK;
  511. }
  512. STDMETHODIMP
  513. CCertTemplateSecurityObject::PropertySheetPageCallback(HWND /*hwnd*/,
  514. UINT uMsg,
  515. SI_PAGE_TYPE /*uPage*/)
  516. {
  517. if ( PSPCB_CREATE == uMsg )
  518. return E_NOTIMPL;
  519. return S_OK;
  520. }