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.

1223 lines
33 KiB

  1. //+--------------------------------------------------------------------------
  2. // File: casd.cpp
  3. // Contents: CCertificateAuthoritySD implementation
  4. //---------------------------------------------------------------------------
  5. #include <pch.cpp>
  6. #include <sid.h>
  7. #include <certsd.h>
  8. #include <certacl.h>
  9. #include <prvlg.h>
  10. #include <sid.h>
  11. //
  12. // MessageId: CERTSRV_E_NO_CAADMIN_DEFINED
  13. //
  14. // MessageText:
  15. //
  16. // At least one security principal must have the permission to manage this CA.
  17. //
  18. #define CERTSRV_E_NO_CAADMIN_DEFINED _HRESULT_TYPEDEF_(0x8009400DL)
  19. LPCWSTR const *CCertificateAuthoritySD::m_pcwszResources; // no free
  20. using namespace CertSrv;
  21. HRESULT CCertificateAuthoritySD::Set(
  22. const PSECURITY_DESCRIPTOR pSD,
  23. bool fSetDSSecurity)
  24. {
  25. HRESULT hr = S_OK;
  26. PSECURITY_DESCRIPTOR pSDCrt; // no free
  27. PSECURITY_DESCRIPTOR pSDNew = NULL;
  28. SECURITY_DESCRIPTOR_CONTROL sdc;
  29. CPrivilegeManager PrivilegeMgr;
  30. CSASSERT(NULL != pSD);
  31. hr = LockGet(&pSDCrt);
  32. _JumpIfError(hr, error, "CProtectedSecurityDescriptor::LockGet");
  33. hr = myMergeSD(pSDCrt, pSD, DACL_SECURITY_INFORMATION, &pSDNew);
  34. _JumpIfError(hr, error, "myMergeSD");
  35. hr = Unlock();
  36. _JumpIfError(hr, error, "CProtectedSecurityDescriptor::Unlock");
  37. hr = CProtectedSecurityDescriptor::Set(pSDNew);
  38. _JumpIfError(hr, error, "CProtectedSecurityDescriptor::Set");
  39. hr = MapAndSetDaclOnObjects(fSetDSSecurity);
  40. _JumpIfError(hr, error, "CCertificateAuthoritySD::MapAndSetDaclOnObjects");
  41. error:
  42. LOCAL_FREE(pSDNew);
  43. return hr;
  44. }
  45. HRESULT CCertificateAuthoritySD::MapAndSetDaclOnObjects(bool fSetDSSecurity)
  46. {
  47. HRESULT hr = S_OK;
  48. PACL pCADacl; // no free
  49. PACL pDSAcl = NULL;
  50. PACL pServiceAcl = NULL;
  51. PSECURITY_DESCRIPTOR pCASD; // no free
  52. BOOL fDaclPresent;
  53. ACL_SIZE_INFORMATION CAAclInfo, DefaultDSAclInfo, DefaultServiceAclInfo;
  54. DWORD dwIndex, dwIndex2, dwIndex3;
  55. PVOID pAce;
  56. DWORD dwDSAclSize=0, dwServiceAclSize=0;
  57. DWORD dwTempSize;
  58. hr = LockGet(&pCASD);
  59. _JumpIfError(hr, error, "CProtectedSecurityDescriptor::LockGet");
  60. hr = myGetSecurityDescriptorDacl(
  61. pCASD,
  62. &pCADacl);
  63. _JumpIfError(hr, error, "myGetSecurityDescriptorDacl");
  64. if(!GetAclInformation(pCADacl,
  65. &CAAclInfo,
  66. sizeof(ACL_SIZE_INFORMATION),
  67. AclSizeInformation))
  68. {
  69. hr = myHLastError();
  70. _JumpError(hr, error, "GetAclInformation");
  71. }
  72. // calculate the DACL size
  73. for(dwIndex = 0; dwIndex < CAAclInfo.AceCount; dwIndex++)
  74. {
  75. if(!GetAce(pCADacl, dwIndex, &pAce))
  76. {
  77. hr = myHLastError();
  78. _JumpError(hr, error, "GetAce");
  79. }
  80. if(fSetDSSecurity)
  81. {
  82. hr = MapAclGetSize(pAce, ObjType_DS, dwTempSize);
  83. _JumpIfError(hr, error, "CCertificateAuthoritySD::MapAclGetSize");
  84. }
  85. dwDSAclSize += dwTempSize;
  86. hr = MapAclGetSize(pAce, ObjType_Service, dwTempSize);
  87. _JumpIfError(hr, error, "CCertificateAuthoritySD::MapAclGetSize");
  88. dwServiceAclSize += dwTempSize;
  89. }
  90. if(fSetDSSecurity)
  91. {
  92. hr = SetDefaultAcl(ObjType_DS);
  93. _JumpIfError(hr, error, "CCertificateAuthoritySD::SetDefaultAcl");
  94. if(!GetAclInformation(m_pDefaultDSAcl,
  95. &DefaultDSAclInfo,
  96. sizeof(ACL_SIZE_INFORMATION),
  97. AclSizeInformation))
  98. {
  99. hr = myHLastError();
  100. _JumpError(hr, error, "GetAclInformation");
  101. }
  102. CSASSERT(0==DefaultDSAclInfo.AclBytesFree);
  103. dwDSAclSize += DefaultDSAclInfo.AclBytesInUse;
  104. pDSAcl = (PACL)LocalAlloc(LMEM_FIXED, dwDSAclSize);
  105. if(!pDSAcl)
  106. {
  107. hr = E_OUTOFMEMORY;
  108. _JumpError(hr, error, "LocalAlloc");
  109. }
  110. if(!InitializeAcl(pDSAcl, dwDSAclSize, ACL_REVISION_DS ))
  111. {
  112. hr = myHLastError();
  113. _JumpError(hr, error, "InitializeAcl");
  114. }
  115. }
  116. hr = SetDefaultAcl(ObjType_Service);
  117. _JumpIfError(hr, error, "CCertificateAuthoritySD::SetDefaultAcl");
  118. if(!GetAclInformation(m_pDefaultServiceAcl,
  119. &DefaultServiceAclInfo,
  120. sizeof(ACL_SIZE_INFORMATION),
  121. AclSizeInformation))
  122. {
  123. hr = myHLastError();
  124. _JumpError(hr, error, "GetAclInformation");
  125. }
  126. CSASSERT(0==DefaultServiceAclInfo.AclBytesFree);
  127. dwServiceAclSize += DefaultServiceAclInfo.AclBytesInUse;
  128. pServiceAcl = (PACL)LocalAlloc(LMEM_FIXED, dwServiceAclSize);
  129. if(!pServiceAcl)
  130. {
  131. hr = E_OUTOFMEMORY;
  132. _JumpError(hr, error, "LocalAlloc");
  133. }
  134. if(!InitializeAcl(pServiceAcl, dwServiceAclSize, ACL_REVISION))
  135. {
  136. hr = myHLastError();
  137. _JumpError(hr, error, "InitializeAcl");
  138. }
  139. // copy deny aces from default service acl
  140. for(dwIndex = 0; dwIndex < DefaultServiceAclInfo.AceCount; dwIndex++)
  141. {
  142. if(!GetAce(m_pDefaultServiceAcl, dwIndex, &pAce))
  143. {
  144. hr = myHLastError();
  145. _JumpError(hr, error, "GetAce");
  146. }
  147. if(((ACCESS_ALLOWED_ACE*)pAce)->Header.AceType != ACCESS_DENIED_ACE_TYPE)
  148. continue;
  149. if(!AddAce(
  150. pServiceAcl,
  151. ACL_REVISION,
  152. MAXDWORD,
  153. pAce,
  154. ((ACE_HEADER*)pAce)->AceSize))
  155. {
  156. hr = myHLastError();
  157. _JumpError(hr, error, "AddAce");
  158. }
  159. }
  160. if(fSetDSSecurity)
  161. {
  162. // copy deny aces from default ds acl
  163. for(dwIndex3 = 0; dwIndex3 < DefaultDSAclInfo.AceCount; dwIndex3++)
  164. {
  165. if(!GetAce(m_pDefaultDSAcl, dwIndex3, &pAce))
  166. {
  167. hr = myHLastError();
  168. _JumpError(hr, error, "GetAce");
  169. }
  170. if(((ACCESS_ALLOWED_ACE*)pAce)->Header.AceType != ACCESS_DENIED_ACE_TYPE &&
  171. ((ACCESS_ALLOWED_ACE*)pAce)->Header.AceType != ACCESS_DENIED_OBJECT_ACE_TYPE)
  172. continue;
  173. if(!AddAce(
  174. pDSAcl,
  175. ACL_REVISION_DS,
  176. MAXDWORD,
  177. pAce,
  178. ((ACE_HEADER*)pAce)->AceSize))
  179. {
  180. hr = myHLastError();
  181. _JumpError(hr, error, "AddAce");
  182. }
  183. }
  184. }
  185. // add mapped deny aces to the DACL
  186. for(dwIndex2 = 0; dwIndex2 < CAAclInfo.AceCount; dwIndex2++)
  187. {
  188. if(!GetAce(pCADacl, dwIndex2, &pAce))
  189. {
  190. hr = myHLastError();
  191. _JumpError(hr, error, "GetAce");
  192. }
  193. if(((ACCESS_ALLOWED_ACE*)pAce)->Header.AceType != ACCESS_DENIED_ACE_TYPE)
  194. continue;
  195. if(fSetDSSecurity)
  196. {
  197. hr = MapAclAddAce(pDSAcl, ObjType_DS, pAce);
  198. _JumpIfError(hr, error, "CCertificateAuthoritySD::MapAclAddAce");
  199. }
  200. hr = MapAclAddAce(pServiceAcl, ObjType_Service, pAce);
  201. _JumpIfError(hr, error, "CCertificateAuthoritySD::MapAclAddAce");
  202. }
  203. // continue with the allow aces from default service acl
  204. for(dwIndex=0; dwIndex < DefaultServiceAclInfo.AceCount; dwIndex++)
  205. {
  206. if(!GetAce(m_pDefaultServiceAcl, dwIndex, &pAce))
  207. {
  208. hr = myHLastError();
  209. _JumpError(hr, error, "GetAce");
  210. }
  211. if(((ACCESS_ALLOWED_ACE*)pAce)->Header.AceType != ACCESS_ALLOWED_ACE_TYPE)
  212. continue;
  213. if(!AddAce(
  214. pServiceAcl,
  215. ACL_REVISION,
  216. MAXDWORD,
  217. pAce,
  218. ((ACE_HEADER*)pAce)->AceSize))
  219. {
  220. hr = myHLastError();
  221. _JumpError(hr, error, "AddAce");
  222. }
  223. }
  224. // continue with the allow aces from default ds acl
  225. if(fSetDSSecurity)
  226. {
  227. for(dwIndex3=0; dwIndex3 < DefaultDSAclInfo.AceCount; dwIndex3++)
  228. {
  229. if(!GetAce(m_pDefaultDSAcl, dwIndex3, &pAce))
  230. {
  231. hr = myHLastError();
  232. _JumpError(hr, error, "GetAce");
  233. }
  234. if(((ACCESS_ALLOWED_ACE*)pAce)->Header.AceType != ACCESS_ALLOWED_ACE_TYPE &&
  235. ((ACCESS_ALLOWED_ACE*)pAce)->Header.AceType != ACCESS_ALLOWED_OBJECT_ACE_TYPE)
  236. continue;
  237. if(!AddAce(
  238. pDSAcl,
  239. ACL_REVISION_DS,
  240. MAXDWORD,
  241. pAce,
  242. ((ACE_HEADER*)pAce)->AceSize))
  243. {
  244. hr = myHLastError();
  245. _JumpError(hr, error, "AddAce");
  246. }
  247. }
  248. }
  249. // continue with the allow mapped aces to the DACL
  250. for(dwIndex2=0;dwIndex2 < CAAclInfo.AceCount; dwIndex2++)
  251. {
  252. if(!GetAce(pCADacl, dwIndex2, &pAce))
  253. {
  254. hr = myHLastError();
  255. _JumpError(hr, error, "GetAce");
  256. }
  257. if(((ACCESS_ALLOWED_ACE*)pAce)->Header.AceType != ACCESS_ALLOWED_ACE_TYPE)
  258. {
  259. continue;
  260. }
  261. if(fSetDSSecurity)
  262. {
  263. hr = MapAclAddAce(pDSAcl, ObjType_DS, pAce);
  264. _JumpIfError(hr, error, "CCertificateAuthoritySD::MapAclAddAce");
  265. }
  266. hr = MapAclAddAce(pServiceAcl, ObjType_Service, pAce);
  267. _JumpIfError(hr, error, "CCertificateAuthoritySD::MapAclAddAce");
  268. }
  269. hr = Unlock();
  270. _JumpIfError(hr, error, "CProtectedSecurityDescriptor::Unlock");
  271. hr = MapAclSetOnService(pServiceAcl);
  272. _JumpIfError(hr, error, "CCertificateAuthoritySD::MapAclSetOnService");
  273. // set DACL on objects
  274. if(fSetDSSecurity)
  275. {
  276. hr = MapAclSetOnDS(pDSAcl);
  277. _JumpIfError(hr, error, "CCertificateAuthoritySD::MapAclSetOnDS");
  278. }
  279. error:
  280. LOCAL_FREE(pDSAcl);
  281. LOCAL_FREE(pServiceAcl);
  282. return hr;
  283. }
  284. HRESULT CCertificateAuthoritySD::MapAclGetSize(
  285. PVOID pAce,
  286. ObjType type,
  287. DWORD& dwSize)
  288. {
  289. ACCESS_ALLOWED_ACE *pAllowAce = (ACCESS_ALLOWED_ACE*)pAce;
  290. // CA acl should contain only ACCESS_ALLOWED_ACE_TYPE
  291. // and ACCESS_DENIED_ACE_TYPE
  292. if(ACCESS_ALLOWED_ACE_TYPE != pAllowAce->Header.AceType &&
  293. ACCESS_DENIED_ACE_TYPE != pAllowAce->Header.AceType)
  294. {
  295. return E_INVALIDARG;
  296. }
  297. dwSize = 0;
  298. switch(type)
  299. {
  300. case ObjType_DS:
  301. // enroll access maps to enroll object ace on DS
  302. if(pAllowAce->Mask & CA_ACCESS_ENROLL)
  303. {
  304. dwSize = sizeof(ACCESS_ALLOWED_OBJECT_ACE) - sizeof(DWORD)+
  305. GetLengthSid((PSID)&(pAllowAce->SidStart));
  306. }
  307. break;
  308. case ObjType_Service:
  309. // ca admin maps to full control on service
  310. if(pAllowAce->Mask & CA_ACCESS_ADMIN)
  311. {
  312. dwSize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)+
  313. GetLengthSid((PSID)&(pAllowAce->SidStart));
  314. }
  315. break;
  316. default:
  317. CSASSERT("Invalid object type" && 0);
  318. }
  319. return S_OK;
  320. }
  321. HRESULT CCertificateAuthoritySD::MapAclAddAce(
  322. PACL pAcl,
  323. ObjType type,
  324. PVOID pAce)
  325. {
  326. ACCESS_ALLOWED_ACE *pCrtAce = (ACCESS_ALLOWED_ACE *)pAce;
  327. bool fAllowAce = (pCrtAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE);
  328. CSASSERT(pCrtAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE ||
  329. pCrtAce->Header.AceType == ACCESS_DENIED_ACE_TYPE);
  330. switch(type)
  331. {
  332. case ObjType_DS:
  333. // enroll access maps to enroll object ace on DS
  334. if(pCrtAce->Mask & CA_ACCESS_ENROLL)
  335. {
  336. if(fAllowAce)
  337. {
  338. if(!AddAccessAllowedObjectAce(
  339. pAcl,
  340. ACL_REVISION_DS,
  341. NO_INHERITANCE,
  342. ACTRL_DS_CONTROL_ACCESS,
  343. const_cast<GUID*>(&GUID_ENROLL),
  344. NULL,
  345. &pCrtAce->SidStart))
  346. {
  347. return myHLastError();
  348. }
  349. }
  350. else
  351. {
  352. if(!AddAccessDeniedObjectAce(
  353. pAcl,
  354. ACL_REVISION_DS,
  355. NO_INHERITANCE,
  356. ACTRL_DS_CONTROL_ACCESS,
  357. const_cast<GUID*>(&GUID_ENROLL),
  358. NULL,
  359. &pCrtAce->SidStart))
  360. {
  361. return myHLastError();
  362. }
  363. }
  364. }
  365. break;
  366. case ObjType_Service:
  367. // ca admin maps to full control on service
  368. if(pCrtAce->Mask & CA_ACCESS_ADMIN)
  369. {
  370. if(fAllowAce)
  371. {
  372. if(!AddAccessAllowedAce(
  373. pAcl,
  374. ACL_REVISION,
  375. SERVICE_ALL_ACCESS,
  376. &pCrtAce->SidStart))
  377. {
  378. return myHLastError();
  379. }
  380. }
  381. else
  382. {
  383. if(!AddAccessDeniedAce(
  384. pAcl,
  385. ACL_REVISION,
  386. SERVICE_ALL_ACCESS,
  387. &pCrtAce->SidStart))
  388. {
  389. return myHLastError();
  390. }
  391. }
  392. }
  393. break;
  394. default:
  395. CSASSERT("Invalid object type" && 0);
  396. }
  397. return S_OK;
  398. }
  399. HRESULT CCertificateAuthoritySD::SetDefaultAcl(ObjType type)
  400. {
  401. HRESULT hr = S_OK;
  402. switch(type)
  403. {
  404. case ObjType_DS:
  405. if(!m_pDefaultDSAcl)
  406. {
  407. hr = SetComputerSID();
  408. _JumpIfError(hr, error, "SetComputerSID");
  409. CSASSERT(!m_pDefaultDSSD);
  410. hr = myGetSDFromTemplate(
  411. WSZ_DEFAULT_DSENROLLMENT_SECURITY,
  412. m_pwszComputerSID,
  413. &m_pDefaultDSSD);
  414. _JumpIfError(hr, error, "myGetSDFromTemplate");
  415. hr = myGetSecurityDescriptorDacl(
  416. m_pDefaultDSSD,
  417. &m_pDefaultDSAcl);
  418. _JumpIfError(hr, error, "myGetSecurityDescriptorDacl");
  419. }
  420. break;
  421. case ObjType_Service:
  422. if(!m_pDefaultServiceAcl)
  423. {
  424. CSASSERT(!m_pDefaultServiceSD);
  425. hr = myGetSDFromTemplate(
  426. WSZ_DEFAULT_SERVICE_SECURITY,
  427. NULL,
  428. &m_pDefaultServiceSD);
  429. _JumpIfError(hr, error, "myGetSDFromTemplate");
  430. hr = myGetSecurityDescriptorDacl(
  431. m_pDefaultServiceSD,
  432. &m_pDefaultServiceAcl);
  433. _JumpIfError(hr, error, "myGetSecurityDescriptorDacl");
  434. }
  435. break;
  436. }
  437. error:
  438. return hr;
  439. }
  440. HRESULT CCertificateAuthoritySD::SetComputerSID()
  441. {
  442. HRESULT hr = S_OK;
  443. LPWSTR pwszDomainName = NULL;
  444. DWORD cDomainName = 0;
  445. LPWSTR pwszComputerName = NULL;
  446. DWORD cbSid;
  447. SID_NAME_USE SidUse;
  448. PBYTE pComputerSID = NULL;
  449. CSASSERT(!m_pwszComputerSID);
  450. hr = myGetComputerObjectName(NameSamCompatible, &pwszComputerName);
  451. _JumpIfError(hr, error, "myGetComputerObjectName");
  452. LookupAccountName(
  453. NULL,
  454. pwszComputerName,
  455. NULL,
  456. &cbSid,
  457. NULL,
  458. &cDomainName,
  459. &SidUse);
  460. if(GetLastError()!=ERROR_INSUFFICIENT_BUFFER)
  461. {
  462. hr = myHLastError();
  463. _JumpError(hr, error, "LookupAccountName");
  464. }
  465. pwszDomainName = (LPWSTR)LocalAlloc(
  466. LMEM_FIXED,
  467. cDomainName*sizeof(WCHAR));
  468. if(!pwszDomainName)
  469. {
  470. hr = E_OUTOFMEMORY;
  471. _JumpError(hr, error, "LocalAlloc");
  472. }
  473. pComputerSID = (LPBYTE)LocalAlloc(
  474. LMEM_FIXED,
  475. cbSid);
  476. if(!pComputerSID)
  477. {
  478. hr = E_OUTOFMEMORY;
  479. _JumpError(hr, error, "LocalAlloc");
  480. }
  481. if(!LookupAccountName(
  482. NULL,
  483. pwszComputerName,
  484. pComputerSID,
  485. &cbSid,
  486. pwszDomainName,
  487. &cDomainName,
  488. &SidUse))
  489. {
  490. hr = myHLastError();
  491. _JumpError(hr, error, "LookupAccountName");
  492. }
  493. if(!myConvertSidToStringSid(
  494. pComputerSID,
  495. &m_pwszComputerSID))
  496. {
  497. hr = myHLastError();
  498. _JumpError(hr, error, "myConvertSidToStringSid");
  499. }
  500. error:
  501. LOCAL_FREE(pwszDomainName);
  502. LOCAL_FREE(pComputerSID);
  503. return hr;
  504. }
  505. typedef LPCWSTR (WINAPI FNCAGETDN)(
  506. IN HCAINFO hCAInfo);
  507. LPCWSTR
  508. myCAGetDN(
  509. IN HCAINFO hCAInfo)
  510. {
  511. HMODULE hModule;
  512. static FNCAGETDN *s_pfn = NULL;
  513. LPCWSTR pwszCADN = NULL;
  514. if (NULL == s_pfn)
  515. {
  516. hModule = GetModuleHandle(TEXT("certcli.dll"));
  517. if (NULL == hModule)
  518. {
  519. goto error;
  520. }
  521. s_pfn = (FNCAGETDN *) GetProcAddress(hModule, "CAGetDN");
  522. if (NULL == s_pfn)
  523. {
  524. goto error;
  525. }
  526. }
  527. pwszCADN = (*s_pfn)(hCAInfo);
  528. error:
  529. return(pwszCADN);
  530. }
  531. HRESULT CCertificateAuthoritySD::MapAclSetOnDS(const PACL pAcl)
  532. {
  533. HRESULT hr = S_OK;
  534. LPWSTR pwszSanitizedDSName = NULL;
  535. HCAINFO hCAInfo;
  536. LPCWSTR pwszCADN;
  537. hr = mySanitizedNameToDSName(m_pcwszSanitizedName, &pwszSanitizedDSName);
  538. _JumpIfError(hr, error, "mySanitizedNameToDSName");
  539. hr = CAFindByName(
  540. pwszSanitizedDSName,
  541. NULL,
  542. CA_FIND_INCLUDE_UNTRUSTED | CA_FIND_INCLUDE_NON_TEMPLATE_CA,
  543. &hCAInfo);
  544. _JumpIfErrorStr(hr, error, "CAFindByName", pwszSanitizedDSName);
  545. pwszCADN = myCAGetDN(hCAInfo);
  546. if (NULL == pwszCADN)
  547. {
  548. hr = myHLastError();
  549. _JumpError(hr, error, "myCAGetDN");
  550. }
  551. hr = SetNamedSecurityInfo(
  552. const_cast<LPWSTR>(pwszCADN),
  553. SE_DS_OBJECT_ALL,
  554. DACL_SECURITY_INFORMATION,
  555. NULL,
  556. NULL,
  557. pAcl,
  558. NULL);
  559. if(ERROR_SUCCESS != hr)
  560. {
  561. if(ERROR_ACCESS_DENIED == hr)
  562. {
  563. // If we can't set the acl on ds enrollment object, notify
  564. // the caller with a special error code so it can take action.
  565. // See bug# 193388
  566. hr = ERROR_CAN_NOT_COMPLETE;
  567. }
  568. hr = myHError(hr);
  569. _JumpError(hr, error, "SetNamedSecurityInfo");
  570. }
  571. error:
  572. LOCAL_FREE(pwszSanitizedDSName);
  573. if(hCAInfo)
  574. CACloseCA(hCAInfo);
  575. return hr;
  576. }
  577. HRESULT CCertificateAuthoritySD::MapAclSetOnService(const PACL pAcl)
  578. {
  579. HRESULT hr = S_OK;
  580. hr = SetNamedSecurityInfo(
  581. wszSERVICE_NAME,
  582. SE_SERVICE,
  583. DACL_SECURITY_INFORMATION,
  584. NULL,
  585. NULL,
  586. pAcl,
  587. NULL);
  588. if(ERROR_SUCCESS != hr)
  589. {
  590. hr = myHError(hr);
  591. _JumpError(hr, error, "SetNamedSecurityInfo");
  592. }
  593. error:
  594. return hr;
  595. }
  596. HRESULT CCertificateAuthoritySD::ResetSACL()
  597. {
  598. HRESULT hr = S_OK;
  599. PSECURITY_DESCRIPTOR pSaclSD = NULL;
  600. PSECURITY_DESCRIPTOR pSDCrt; // no free
  601. PSECURITY_DESCRIPTOR pSDNew = NULL;
  602. hr = myGetSDFromTemplate(
  603. CERTSRV_SACL_ON,
  604. NULL,
  605. &pSaclSD);
  606. _JumpIfError(hr, error, "myGetSDFromTemplate");
  607. hr = LockGet(&pSDCrt);
  608. _JumpIfError(hr, error, "CProtectedSecurityDescriptor::LockGet");
  609. hr = myMergeSD(pSDCrt, pSaclSD, SACL_SECURITY_INFORMATION, &pSDNew);
  610. _JumpIfError(hr, error, "myMergeSD");
  611. hr = Unlock();
  612. _JumpIfError(hr, error, "CProtectedSecurityDescriptor::Unlock");
  613. hr = CProtectedSecurityDescriptor::Set(pSDNew);
  614. _JumpIfError(hr, error, "CProtectedSecurityDescriptor::Set");
  615. error:
  616. LOCAL_FREE(pSaclSD);
  617. LOCAL_FREE(pSDNew);
  618. return hr;
  619. }
  620. // Upgrade from CA security descriptor from win2k.
  621. //
  622. // Allow aces are mapped as follows:
  623. // manage -> CA admin + officer
  624. // enroll -> enroll
  625. // read -> read
  626. // revoke -> officer
  627. // approve -> officer
  628. // else -> read
  629. //
  630. // Deny aces are ignored.
  631. HRESULT CCertificateAuthoritySD::UpgradeWin2k(
  632. bool fUseEnterpriseAcl)
  633. {
  634. HRESULT hr = S_OK;
  635. PSECURITY_DESCRIPTOR pSDOld; // no free
  636. PACL pAclOld; // no free
  637. PSECURITY_DESCRIPTOR pSDNewDaclOnly = NULL;
  638. PSECURITY_DESCRIPTOR pSDNewSaclOnly = NULL;
  639. PSECURITY_DESCRIPTOR pSDNew = NULL;
  640. PACL pAclNew = NULL;
  641. ACL_SIZE_INFORMATION OldAclSizeInfo;
  642. DWORD dwSizeAclNew = sizeof(ACL);
  643. DWORD cAce;
  644. PVOID pAce;
  645. ACCESS_MASK dwAccessMask;
  646. PSID pSid; // no free
  647. hr = LockGet(&pSDOld);
  648. _JumpIfError(hr, error, "CProtectedSecurityDescriptor::LockGet");
  649. hr = myGetSecurityDescriptorDacl(
  650. pSDOld,
  651. &pAclOld);
  652. _JumpIfError(hr, error, "myGetSecurityDescriptorDacl");
  653. if(!GetAclInformation(pAclOld,
  654. &OldAclSizeInfo,
  655. sizeof(ACL_SIZE_INFORMATION),
  656. AclSizeInformation))
  657. {
  658. hr = myHLastError();
  659. _JumpError(hr, error, "GetAclInformation");
  660. }
  661. for(cAce=0;cAce<OldAclSizeInfo.AceCount;cAce++)
  662. {
  663. if(!GetAce(pAclOld, cAce, &pAce))
  664. {
  665. hr = myHLastError();
  666. _JumpError(hr, error, "GetAce");
  667. }
  668. dwSizeAclNew += GetUpgradeAceSizeAndType(pAce, NULL, NULL);
  669. }
  670. // if no valid ACE found, fall back to a default SD
  671. if(sizeof(ACL)==dwSizeAclNew)
  672. {
  673. hr= myGetSDFromTemplate(
  674. fUseEnterpriseAcl?
  675. WSZ_DEFAULT_CA_ENT_SECURITY:
  676. WSZ_DEFAULT_CA_STD_SECURITY,
  677. NULL,
  678. &pSDNew);
  679. _JumpIfError(hr, error, "myGetSDFromTemplate");
  680. }
  681. else
  682. {
  683. pAclNew = (PACL)LocalAlloc(LMEM_FIXED, dwSizeAclNew);
  684. if(!pAclNew)
  685. {
  686. hr = E_OUTOFMEMORY;
  687. _JumpError(hr, error, "LocalAlloc");
  688. }
  689. FillMemory(pAclNew, dwSizeAclNew, L' ');
  690. if(!InitializeAcl(pAclNew, dwSizeAclNew, ACL_REVISION))
  691. {
  692. hr = myHLastError();
  693. _JumpError(hr, error, "InitializeAcl");
  694. }
  695. for(cAce=0;cAce<OldAclSizeInfo.AceCount;cAce++)
  696. {
  697. if(!GetAce(pAclOld, cAce, &pAce))
  698. {
  699. hr = myHLastError();
  700. _JumpError(hr, error, "GetAce");
  701. }
  702. if(GetUpgradeAceSizeAndType(
  703. pAce,
  704. &dwAccessMask,
  705. &pSid))
  706. {
  707. BYTE acetype = ((ACCESS_ALLOWED_ACE*)pAce)->Header.AceType;
  708. switch(acetype)
  709. {
  710. case ACCESS_ALLOWED_ACE_TYPE:
  711. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  712. if(!AddAccessAllowedAce(
  713. pAclNew,
  714. ACL_REVISION,
  715. dwAccessMask,
  716. pSid))
  717. {
  718. hr = myHLastError();
  719. _JumpError(hr, error, "AddAccessAllowed");
  720. }
  721. break;
  722. case ACCESS_DENIED_ACE_TYPE:
  723. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  724. if(!AddAccessDeniedAce(
  725. pAclNew,
  726. ACL_REVISION,
  727. dwAccessMask,
  728. pSid))
  729. {
  730. hr = myHLastError();
  731. _JumpError(hr, error, "AddAccessAllowed");
  732. }
  733. break;
  734. }
  735. }
  736. }
  737. // Build a new SD based on this DACL
  738. pSDNewDaclOnly = (PSECURITY_DESCRIPTOR)LocalAlloc(
  739. LMEM_FIXED,
  740. SECURITY_DESCRIPTOR_MIN_LENGTH);
  741. if (!pSDNewDaclOnly)
  742. {
  743. hr = E_OUTOFMEMORY;
  744. _JumpError(hr, error, "LocalAlloc");
  745. }
  746. if (!InitializeSecurityDescriptor(
  747. pSDNewDaclOnly,
  748. SECURITY_DESCRIPTOR_REVISION))
  749. {
  750. hr = myHLastError();
  751. _JumpError(hr, error, "InitializeSecurityDescriptor");
  752. }
  753. if(!SetSecurityDescriptorDacl(pSDNewDaclOnly,
  754. TRUE,
  755. pAclNew,
  756. FALSE))
  757. {
  758. hr = myHLastError();
  759. _JumpError(hr, error, "SetSecurityDescriptorDacl");
  760. }
  761. hr= myGetSDFromTemplate(
  762. WSZ_DEFAULT_CA_STD_SECURITY,
  763. NULL,
  764. &pSDNewSaclOnly);
  765. _JumpIfError(hr, error, "myGetSDFromTemplate");
  766. // merge SACL & DACL in new SD
  767. hr = myMergeSD(
  768. pSDNewSaclOnly,
  769. pSDNewDaclOnly,
  770. DACL_SECURITY_INFORMATION,
  771. &pSDNew);
  772. _JumpIfError(hr, error, "myMergeSD");
  773. CSASSERT(IsValidSecurityDescriptor(pSDNew));
  774. }
  775. hr = Unlock();
  776. _JumpIfError(hr, error, "CProtectedSecurityDescriptor::Unlock");
  777. hr = CProtectedSecurityDescriptor::Set(pSDNew);
  778. _JumpIfError(hr, error, "CProtectedSecurityDescriptor::Set");
  779. error:
  780. LOCAL_FREE(pSDNew);
  781. LOCAL_FREE(pSDNewSaclOnly);
  782. LOCAL_FREE(pSDNewDaclOnly);
  783. LOCAL_FREE(pAclNew);
  784. return hr;
  785. }
  786. DWORD CCertificateAuthoritySD::GetUpgradeAceSizeAndType(
  787. PVOID pAce, DWORD *pdwType, PSID *ppSid)
  788. {
  789. DWORD dwSize = 0;
  790. PSID pSid = NULL;
  791. DWORD dwType = 0;
  792. switch(((PACCESS_ALLOWED_ACE)pAce)->Header.AceType)
  793. {
  794. case ACCESS_ALLOWED_ACE_TYPE:
  795. case ACCESS_DENIED_ACE_TYPE:
  796. pSid = (PSID)&(((PACCESS_ALLOWED_ACE)pAce)->SidStart);
  797. dwSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD)+GetLengthSid(pSid);
  798. switch(((PACCESS_ALLOWED_ACE)pAce)->Mask)
  799. {
  800. case ACTRL_CERTSRV_MANAGE:
  801. dwType = CA_ACCESS_ADMIN | CA_ACCESS_OFFICER;
  802. break;
  803. default: // including ACTRL_CERTSRV_READ
  804. dwType = CA_ACCESS_READ;
  805. }
  806. break;
  807. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  808. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  809. PACCESS_ALLOWED_OBJECT_ACE pObjAce = (PACCESS_ALLOWED_OBJECT_ACE)pAce;
  810. pSid = (PSID)(((BYTE*)(&pObjAce->ObjectType))+
  811. ((pObjAce->Flags&ACE_OBJECT_TYPE_PRESENT)?
  812. sizeof(pObjAce->ObjectType):0)+
  813. ((pObjAce->Flags&ACE_INHERITED_OBJECT_TYPE_PRESENT)?
  814. sizeof(pObjAce->InheritedObjectType):0));
  815. dwSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD)+GetLengthSid(pSid);
  816. REFGUID rGUID = (((PACCESS_ALLOWED_OBJECT_ACE)pAce)->ObjectType);
  817. if(IsEqualGUID(rGUID, GUID_ENROLL))
  818. {
  819. dwType = CA_ACCESS_ENROLL;
  820. } else
  821. if(IsEqualGUID(rGUID, GUID_APPRV_REQ) ||
  822. IsEqualGUID(rGUID, GUID_REVOKE))
  823. {
  824. dwType = CA_ACCESS_OFFICER;
  825. } else
  826. {
  827. dwType = CA_ACCESS_READ;
  828. }
  829. break;
  830. // denied aces are not upgraded so ignore them
  831. }
  832. if(ppSid)
  833. *ppSid = pSid;
  834. if(pdwType)
  835. *pdwType = dwType;
  836. return dwSize;
  837. }
  838. // Returns:
  839. // - E_INVALIDARG: invalid ACEs found,
  840. // - S_FALSE: no admin ACE found (to avoid admins locking themselves out)
  841. HRESULT CCertificateAuthoritySD::Validate(PSECURITY_DESCRIPTOR pSD)
  842. {
  843. HRESULT hr;
  844. ACL_SIZE_INFORMATION AclInfo;
  845. DWORD dwIndex;
  846. PACCESS_ALLOWED_ACE pAce; // no free
  847. PACL pDacl; // no free
  848. bool fAdminAceFound = false;
  849. DWORD dwKnownRights = CA_ACCESS_ADMIN |
  850. CA_ACCESS_OFFICER |
  851. CA_ACCESS_READ |
  852. CA_ACCESS_ENROLL;
  853. if(!IsValidSecurityDescriptor(pSD))
  854. {
  855. hr = myHLastError();
  856. _JumpError(hr, error, "IsValidSecurityDescriptor");
  857. }
  858. // get acl
  859. hr = myGetSecurityDescriptorDacl(
  860. pSD,
  861. &pDacl);
  862. _JumpIfError(hr, error, "myGetDaclFromInfoSecurityDescriptor");
  863. if(!GetAclInformation(pDacl,
  864. &AclInfo,
  865. sizeof(ACL_SIZE_INFORMATION),
  866. AclSizeInformation))
  867. {
  868. hr = myHLastError();
  869. _JumpError(hr, error, "GetAclInformation");
  870. }
  871. for(dwIndex = 0; dwIndex < AclInfo.AceCount; dwIndex++)
  872. {
  873. if(!GetAce(pDacl, dwIndex, (LPVOID*)&pAce))
  874. {
  875. hr = myHLastError();
  876. _JumpError(hr, error, "GetAce");
  877. }
  878. // only access allowed/denied aces and know rights are allowed
  879. if((ACCESS_ALLOWED_ACE_TYPE!=pAce->Header.AceType &&
  880. ACCESS_DENIED_ACE_TYPE !=pAce->Header.AceType) ||
  881. (~dwKnownRights & pAce->Mask))
  882. {
  883. return E_INVALIDARG;
  884. }
  885. if((CA_ACCESS_ADMIN & pAce->Mask) &&
  886. (ACCESS_ALLOWED_ACE_TYPE==pAce->Header.AceType))
  887. {
  888. fAdminAceFound = true;
  889. }
  890. }
  891. // no caadmin allow ace found
  892. hr = fAdminAceFound?S_OK:CERTSRV_E_NO_CAADMIN_DEFINED;
  893. error:
  894. return hr;
  895. }
  896. HRESULT CCertificateAuthoritySD::ConvertToString(
  897. IN PSECURITY_DESCRIPTOR pSD,
  898. OUT LPWSTR& rpwszSD)
  899. {
  900. HRESULT hr = S_OK;
  901. LPCWSTR pcwszHeader = L"\n"; // start with a new line
  902. DWORD dwBufSize = sizeof(WCHAR)*(wcslen(pcwszHeader)+1);
  903. ACL_SIZE_INFORMATION AclInfo;
  904. DWORD dwIndex;
  905. PACCESS_ALLOWED_ACE pAce; // no free
  906. PACL pDacl; // no free
  907. LPWSTR pwszAce; // no free
  908. rpwszSD = NULL;
  909. hr = Validate(pSD);
  910. _JumpIfError(hr, error, "CCertificateAuthoritySD::Validate");
  911. // get acl
  912. hr = myGetSecurityDescriptorDacl(
  913. pSD,
  914. &pDacl);
  915. _JumpIfError(hr, error, "myGetDaclFromInfoSecurityDescriptor");
  916. if(!GetAclInformation(pDacl,
  917. &AclInfo,
  918. sizeof(ACL_SIZE_INFORMATION),
  919. AclSizeInformation))
  920. {
  921. hr = myHLastError();
  922. _JumpError(hr, error, "GetAclInformation");
  923. }
  924. // calculate text size
  925. for(dwIndex = 0; dwIndex < AclInfo.AceCount; dwIndex++)
  926. {
  927. DWORD dwAceSize;
  928. if(!GetAce(pDacl, dwIndex, (LPVOID*)&pAce))
  929. {
  930. hr = myHLastError();
  931. _JumpError(hr, error, "GetAce");
  932. }
  933. hr = ConvertAceToString(
  934. pAce,
  935. &dwAceSize,
  936. NULL);
  937. _JumpIfError(hr, error, "ConvertAceToString");
  938. dwBufSize += dwAceSize;
  939. }
  940. rpwszSD = (LPWSTR)LocalAlloc(LMEM_FIXED, dwBufSize);
  941. _JumpIfAllocFailed(rpwszSD, error);
  942. // build the output string
  943. wcscpy(rpwszSD, pcwszHeader);
  944. pwszAce = rpwszSD + wcslen(pcwszHeader);
  945. for(dwIndex = 0; dwIndex < AclInfo.AceCount; dwIndex++)
  946. {
  947. DWORD dwAceSize;
  948. if(!GetAce(pDacl, dwIndex, (LPVOID*)&pAce))
  949. {
  950. hr = myHLastError();
  951. _JumpError(hr, error, "GetAce");
  952. }
  953. hr = ConvertAceToString(
  954. pAce,
  955. &dwAceSize,
  956. pwszAce);
  957. _JumpIfError(hr, error, "ConvertAceToString");
  958. pwszAce += dwAceSize/sizeof(WCHAR);
  959. }
  960. error:
  961. return hr;
  962. }
  963. // Returned string has the following format:
  964. //
  965. // [Allow|Deny]\t[Name|SID]\n
  966. // \tRole1\n
  967. // \tRole2\n
  968. // ...
  969. //
  970. // Example:
  971. //
  972. // Allow Administrators
  973. // CA Administrator
  974. // Certificate Manager
  975. //
  976. // If SID cannot be converted to friendly name it is displayed
  977. // as a string SID
  978. //
  979. HRESULT CCertificateAuthoritySD::ConvertAceToString(
  980. IN PACCESS_ALLOWED_ACE pAce,
  981. OUT OPTIONAL PDWORD pdwSize,
  982. IN OUT OPTIONAL LPWSTR pwszSD)
  983. {
  984. HRESULT hr = S_OK;
  985. DWORD dwSize = 1; // trailing '\0'
  986. CSid sid((PSID)(&pAce->SidStart));
  987. LPCWSTR pcwszAllow = m_pcwszResources[0];
  988. LPCWSTR pcwszDeny = m_pcwszResources[1];
  989. LPCWSTR pcwszPermissionType =
  990. (ACCESS_ALLOWED_ACE_TYPE==pAce->Header.AceType)?
  991. pcwszAllow:pcwszDeny;
  992. LPCWSTR pcwszSid; // no free
  993. DWORD dwRoles[] =
  994. {
  995. CA_ACCESS_ADMIN,
  996. CA_ACCESS_OFFICER,
  997. CA_ACCESS_READ,
  998. CA_ACCESS_ENROLL,
  999. };
  1000. // dwRoles and resources should match the roles
  1001. const LPCWSTR *pcwszRoles = &m_pcwszResources[2];
  1002. DWORD cRoles;
  1003. // asked for size and/or ace string
  1004. CSASSERT(pdwSize || pwszSD);
  1005. pcwszSid = sid.GetName();
  1006. if(!pcwszSid)
  1007. {
  1008. return E_OUTOFMEMORY;
  1009. }
  1010. dwSize = wcslen(pcwszSid);
  1011. dwSize += wcslen(pcwszPermissionType);
  1012. dwSize += 2; // '\t' between sid an permission and a '\n' after
  1013. if(pwszSD)
  1014. {
  1015. wcscat(pwszSD, pcwszPermissionType);
  1016. wcscat(pwszSD, L"\t");
  1017. wcscat(pwszSD, pcwszSid);
  1018. wcscat(pwszSD, L"\n");
  1019. }
  1020. for(cRoles=0;cRoles<ARRAYSIZE(dwRoles);cRoles++)
  1021. {
  1022. if(pAce->Mask & dwRoles[cRoles])
  1023. {
  1024. dwSize += wcslen(pcwszRoles[cRoles]) + 2; // "\tRole\n"
  1025. if(pwszSD)
  1026. {
  1027. wcscat(pwszSD, L"\t");
  1028. wcscat(pwszSD, pcwszRoles[cRoles]);
  1029. wcscat(pwszSD, L"\n");
  1030. }
  1031. }
  1032. }
  1033. dwSize *= sizeof(WCHAR);
  1034. if(pdwSize)
  1035. {
  1036. *pdwSize = dwSize;
  1037. }
  1038. return hr;
  1039. }