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.

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