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.

1585 lines
38 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: certwrap.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include <stdafx.h>
  11. #include "csdisp.h"
  12. #include "certsrv.h"
  13. #include "genpage.h"
  14. #include "progress.h"
  15. #include "misc.h"
  16. #include "certacl.h"
  17. #include <dsgetdc.h>
  18. #include <winldap.h>
  19. #include "csldap.h"
  20. _COM_SMARTPTR_TYPEDEF(IADs, IID_IADs);
  21. //////////////////////////
  22. // CertSvrCA class
  23. CertSvrCA::CertSvrCA(CertSvrMachine* pParent) :
  24. m_pParentMachine(pParent)
  25. {
  26. m_hCACertStore = NULL;
  27. m_fCertStoreOpenAttempted = FALSE;
  28. m_hrCACertStoreOpen = S_OK;
  29. m_hRootCertStore = NULL;
  30. m_fRootStoreOpenAttempted = FALSE;
  31. m_hrRootCertStoreOpen = S_OK;
  32. m_hKRACertStore = NULL;
  33. m_fKRAStoreOpenAttempted = FALSE;
  34. m_hrKRACertStoreOpen = S_OK;
  35. m_bstrConfig = NULL;
  36. m_enumCAType = ENUM_UNKNOWN_CA;
  37. m_fCATypeKnown = FALSE;
  38. m_fIsUsingDS = FALSE;
  39. m_fIsUsingDSKnown = FALSE;
  40. m_fAdvancedServer = FALSE;
  41. m_fAdvancedServerKnown = FALSE;
  42. if(m_pParentMachine)
  43. m_pParentMachine->AddRef();
  44. m_dwRoles = 0;
  45. m_fRolesKnown = FALSE;
  46. }
  47. CertSvrCA::~CertSvrCA()
  48. {
  49. if (m_hCACertStore)
  50. {
  51. CertCloseStore(m_hCACertStore, 0);
  52. m_hCACertStore = NULL;
  53. }
  54. if (m_hRootCertStore)
  55. {
  56. CertCloseStore(m_hRootCertStore, 0);
  57. m_hRootCertStore = NULL;
  58. }
  59. if (m_hKRACertStore)
  60. {
  61. CertCloseStore(m_hKRACertStore, 0);
  62. m_hKRACertStore = NULL;
  63. }
  64. if (m_bstrConfig)
  65. SysFreeString(m_bstrConfig);
  66. if(m_pParentMachine)
  67. m_pParentMachine->Release();
  68. }
  69. BOOL CertSvrCA::AccessAllowed(DWORD dwAccess)
  70. {
  71. return (dwAccess & GetMyRoles())?TRUE:FALSE;
  72. }
  73. DWORD CertSvrCA::GetMyRoles()
  74. {
  75. HRESULT hr = S_OK;
  76. ICertAdmin2Ptr pCertAdmin;
  77. LONG dwRoles;
  78. if(!m_fRolesKnown)
  79. {
  80. hr = m_pParentMachine->GetAdmin2(&pCertAdmin);
  81. _JumpIfError(hr, error, "CertSvrMachine::GetAdmin2");
  82. hr = pCertAdmin->GetMyRoles(
  83. m_bstrConfig,
  84. &dwRoles);
  85. _JumpIfError(hr, error, "ICertAdmin2::GetCAProperty");
  86. m_dwRoles = dwRoles;
  87. m_fRolesKnown = TRUE;
  88. }
  89. error:
  90. return m_dwRoles;
  91. }
  92. HRESULT CertSvrCA::GetCAFlagsFromDS(PDWORD pdwFlags)
  93. {
  94. HRESULT hr = S_OK;
  95. LPWSTR pwszSanitizedDSName = NULL;
  96. HCAINFO hCAInfo = NULL;
  97. hr = mySanitizedNameToDSName(m_strSanitizedName, &pwszSanitizedDSName);
  98. _JumpIfError(hr, error, "mySanitizedNameToDSName");
  99. hr = CAFindByName(
  100. pwszSanitizedDSName,
  101. NULL,
  102. 0,
  103. &hCAInfo);
  104. _JumpIfErrorStr(hr, error, "CAFindByName", pwszSanitizedDSName);
  105. hr = CAGetCAFlags(
  106. hCAInfo,
  107. pdwFlags);
  108. _JumpIfError(hr, error, "CAGetCAFlags");
  109. error:
  110. LOCAL_FREE(pwszSanitizedDSName);
  111. if(hCAInfo)
  112. CACloseCA(hCAInfo);
  113. return hr;
  114. }
  115. // CA machine should have full control over the enrollment object in DS.
  116. // This function checks if the machine has the rights and adds a new
  117. // ace allowing CA machine obj (eg TESTDOMAIN\BOGDANTTEST$) full control
  118. // over its enrollment object
  119. // See bug# 193388.
  120. HRESULT CertSvrCA::FixEnrollmentObject()
  121. {
  122. HRESULT hr = S_OK;
  123. IDirectoryObject *pADEnrollObj = NULL;
  124. LPWSTR pwszAttr = L"nTSecurityDescriptor";
  125. PADS_ATTR_INFO paai = NULL;
  126. DWORD dwAttrReturned;
  127. LPWSTR pwszSanitizedDSName = NULL;
  128. CString strEnrollDN;
  129. HCAINFO hCAInfo = NULL;
  130. PSID pSid = NULL;
  131. bool fAllowed = false;
  132. PSECURITY_DESCRIPTOR pSDRead = NULL; // no free
  133. PSECURITY_DESCRIPTOR pSDWrite = NULL;
  134. hr = mySanitizedNameToDSName(m_strSanitizedName, &pwszSanitizedDSName);
  135. _JumpIfError(hr, error, "mySanitizedNameToDSName");
  136. hr = CAFindByName(
  137. pwszSanitizedDSName,
  138. NULL,
  139. CA_FIND_INCLUDE_UNTRUSTED | CA_FIND_INCLUDE_NON_TEMPLATE_CA,
  140. &hCAInfo);
  141. _JumpIfErrorStr(hr, error, "CAFindByName", pwszSanitizedDSName);
  142. strEnrollDN = L"LDAP://";
  143. strEnrollDN += myCAGetDN(hCAInfo);
  144. if (strEnrollDN.IsEmpty())
  145. {
  146. hr = myHLastError();
  147. _JumpError(hr, error, "myCAGetDN");
  148. }
  149. hr = ADsGetObject(strEnrollDN, IID_IDirectoryObject, (void**)&pADEnrollObj);
  150. _JumpIfErrorStr(hr, error, "ADsGetObject", strEnrollDN);
  151. hr = pADEnrollObj->GetObjectAttributes(
  152. &pwszAttr,
  153. 1,
  154. &paai,
  155. &dwAttrReturned);
  156. _JumpIfErrorStr(hr, error, "Get SD", strEnrollDN);
  157. pSDRead = paai[0].pADsValues[0].SecurityDescriptor.lpValue;
  158. CSASSERT(IsValidSecurityDescriptor(pSDRead));
  159. hr = FindComputerObjectSid(
  160. m_strServer,
  161. pSid);
  162. _JumpIfErrorStr(hr, error, "FindCAComputerObjectSid", m_strServer);
  163. // look in DACL for a ace allowing CA full control
  164. hr = IsCAAllowedFullControl(
  165. pSDRead,
  166. pSid,
  167. fAllowed);
  168. _JumpIfError(hr, error, "IsCAAllowedFullControl");
  169. if(!fAllowed)
  170. {
  171. // build new SD allowing CA full control and write it back
  172. // to DS
  173. ADSVALUE snValue;
  174. ADS_ATTR_INFO attrInfo[] =
  175. {{
  176. pwszAttr,
  177. ADS_ATTR_UPDATE,
  178. ADSTYPE_NT_SECURITY_DESCRIPTOR,
  179. &snValue,
  180. 1}
  181. };
  182. hr = AllowCAFullControl(
  183. pSDRead,
  184. pSid,
  185. pSDWrite);
  186. _JumpIfError(hr, error, "AllowCAFullControl");
  187. CSASSERT(IsValidSecurityDescriptor(pSDWrite));
  188. snValue.dwType = ADSTYPE_NT_SECURITY_DESCRIPTOR;
  189. snValue.SecurityDescriptor.dwLength =
  190. GetSecurityDescriptorLength(pSDWrite);
  191. snValue.SecurityDescriptor.lpValue = (LPBYTE)pSDWrite;
  192. hr = pADEnrollObj->SetObjectAttributes(
  193. attrInfo,
  194. 1,
  195. &dwAttrReturned);
  196. _JumpIfErrorStr(hr, error, "Set SD", strEnrollDN);
  197. }
  198. error:
  199. if(paai)
  200. FreeADsMem(paai);
  201. if(pADEnrollObj)
  202. pADEnrollObj->Release();
  203. if(hCAInfo)
  204. CACloseCA(hCAInfo);
  205. LOCAL_FREE(pwszSanitizedDSName);
  206. LOCAL_FREE(pSid);
  207. LOCAL_FREE(pSDWrite);
  208. return hr;
  209. }
  210. HRESULT CertSvrCA::IsCAAllowedFullControl(
  211. PSECURITY_DESCRIPTOR pSDRead,
  212. PSID pSid,
  213. bool& fAllowed)
  214. {
  215. HRESULT hr = S_OK;
  216. PACL pDacl; // no free
  217. ACL_SIZE_INFORMATION AclInfo;
  218. PACCESS_ALLOWED_ACE pAce; // no free
  219. DWORD dwIndex;
  220. fAllowed = false;
  221. hr = myGetSecurityDescriptorDacl(
  222. pSDRead,
  223. &pDacl);
  224. _JumpIfError(hr, error, "myGetSecurityDescriptorDacl");
  225. if(!GetAclInformation(pDacl,
  226. &AclInfo,
  227. sizeof(ACL_SIZE_INFORMATION),
  228. AclSizeInformation))
  229. {
  230. hr = myHLastError();
  231. _JumpError(hr, error, "GetAclInformation");
  232. }
  233. for(dwIndex = 0; dwIndex < AclInfo.AceCount; dwIndex++)
  234. {
  235. if(!GetAce(pDacl, dwIndex, (LPVOID*)&pAce))
  236. {
  237. hr = myHLastError();
  238. _JumpError(hr, error, "GetAce");
  239. }
  240. if(pAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE &&
  241. (pAce->Mask & ACTRL_CERTSRV_MANAGE) == ACTRL_CERTSRV_MANAGE &&
  242. EqualSid((PSID)&pAce->SidStart, pSid))
  243. {
  244. fAllowed = true;
  245. break;
  246. }
  247. }
  248. error:
  249. return hr;
  250. }
  251. HRESULT CertSvrCA::AllowCAFullControl(
  252. PSECURITY_DESCRIPTOR pSDRead,
  253. PSID pSid,
  254. PSECURITY_DESCRIPTOR& pSDWrite)
  255. {
  256. HRESULT hr = S_OK;
  257. BOOL fRet = 0;
  258. LPBYTE pSDTemp = NULL;
  259. PACL pDaclWrite = NULL;
  260. PACL pDaclRead = NULL; // no free
  261. PVOID pAce = NULL; // no free
  262. DWORD dwAbsoluteSDSize = 0;
  263. DWORD dwDaclSize = 0;
  264. DWORD dwSaclSize = 0;
  265. DWORD dwOwnerSize = 0;
  266. DWORD dwGroupSize = 0;
  267. DWORD dwSDWriteSize = 0;
  268. DWORD dwDaclWriteSize = 0;
  269. hr = myGetSecurityDescriptorDacl(
  270. pSDRead,
  271. &pDaclRead);
  272. _JumpIfError(hr, error, "myGetSecurityDescriptorDacl");
  273. fRet = MakeAbsoluteSD(
  274. pSDRead,
  275. NULL,
  276. &dwAbsoluteSDSize,
  277. NULL,
  278. &dwDaclSize,
  279. NULL,
  280. &dwSaclSize,
  281. NULL,
  282. &dwOwnerSize,
  283. NULL,
  284. &dwGroupSize); // should always fail with insufficient buffer
  285. if(fRet || ERROR_INSUFFICIENT_BUFFER!=GetLastError())
  286. {
  287. hr = fRet?E_FAIL:HRESULT_FROM_WIN32(GetLastError());
  288. _JumpError(hr, error, "MakeAbsoluteSD");
  289. }
  290. // alloc all buffers together
  291. pSDTemp = (LPBYTE)LocalAlloc(
  292. LMEM_FIXED,
  293. dwAbsoluteSDSize+dwDaclSize+dwSaclSize+dwOwnerSize+dwGroupSize);
  294. _JumpIfAllocFailed(pSDTemp, error);
  295. fRet = MakeAbsoluteSD(
  296. pSDRead,
  297. (PSECURITY_DESCRIPTOR)pSDTemp,
  298. &dwAbsoluteSDSize,
  299. (PACL)(pSDTemp+dwAbsoluteSDSize),
  300. &dwDaclSize,
  301. (PACL)(pSDTemp+dwAbsoluteSDSize+dwDaclSize),
  302. &dwSaclSize,
  303. (PSID)(pSDTemp+dwAbsoluteSDSize+dwDaclSize+dwSaclSize),
  304. &dwOwnerSize,
  305. (PSID)(pSDTemp+dwAbsoluteSDSize+dwDaclSize+dwSaclSize+dwOwnerSize),
  306. &dwGroupSize); // should always fail with insufficient buffer
  307. if(!fRet)
  308. {
  309. hr = HRESULT_FROM_WIN32(GetLastError());
  310. _JumpError(hr, error, "MakeAbsoluteSD");
  311. }
  312. dwDaclWriteSize = dwDaclSize+sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD)+
  313. GetLengthSid(pSid);
  314. pDaclWrite = (PACL) LocalAlloc(LMEM_FIXED, dwDaclWriteSize);
  315. _JumpIfAllocFailed(pDaclWrite, error);
  316. fRet = InitializeAcl(pDaclWrite, dwDaclWriteSize, ACL_REVISION_DS);
  317. if(!fRet)
  318. {
  319. hr=HRESULT_FROM_WIN32(GetLastError());
  320. _JumpError(hr, error, "InitializeAcl");
  321. }
  322. fRet = GetAce(pDaclRead, 0, &pAce);
  323. if(!fRet)
  324. {
  325. hr = HRESULT_FROM_WIN32(GetLastError());
  326. _JumpError(hr, error, "GetAce");
  327. }
  328. fRet = AddAce(pDaclWrite, ACL_REVISION_DS, 0, pAce, dwDaclSize-sizeof(ACL));
  329. if(!fRet)
  330. {
  331. hr = HRESULT_FROM_WIN32(GetLastError());
  332. _JumpError(hr, error, "AddAce");
  333. }
  334. fRet = AddAccessAllowedAce(
  335. pDaclWrite,
  336. ACL_REVISION_DS,
  337. ACTRL_CERTSRV_MANAGE_LESS_CONTROL_ACCESS,
  338. pSid);
  339. if(!fRet)
  340. {
  341. hr = HRESULT_FROM_WIN32(GetLastError());
  342. _JumpError(hr, error, "AddAccessAllowedAce");
  343. }
  344. fRet = SetSecurityDescriptorDacl(
  345. pSDTemp,
  346. TRUE,
  347. pDaclWrite,
  348. FALSE);
  349. if(!fRet)
  350. {
  351. hr = HRESULT_FROM_WIN32(GetLastError());
  352. _JumpError(hr, error, "SetSecurityDescriptorDacl");
  353. }
  354. fRet = MakeSelfRelativeSD(
  355. pSDTemp,
  356. NULL,
  357. &dwSDWriteSize);
  358. if(fRet || ERROR_INSUFFICIENT_BUFFER!=GetLastError())
  359. {
  360. hr = fRet?E_FAIL:HRESULT_FROM_WIN32(GetLastError());
  361. _JumpError(hr, error, "MakeSelfRelativeSD");
  362. }
  363. pSDWrite = LocalAlloc(LMEM_FIXED, dwSDWriteSize);
  364. _JumpIfAllocFailed(pSDWrite, error);
  365. fRet = MakeSelfRelativeSD(
  366. pSDTemp,
  367. pSDWrite,
  368. &dwSDWriteSize);
  369. if(!fRet)
  370. {
  371. hr = HRESULT_FROM_WIN32(GetLastError());
  372. _JumpError(hr, error, "MakeSelfRelativeSD");
  373. }
  374. error:
  375. LOCAL_FREE(pSDTemp);
  376. LOCAL_FREE(pDaclWrite);
  377. return hr;
  378. }
  379. BOOL CertSvrCA::FIsUsingDS()
  380. {
  381. DWORD dwRet;
  382. variant_t varUsingDS;
  383. if (m_fIsUsingDSKnown)
  384. return m_fIsUsingDS;
  385. dwRet = GetConfigEntry(
  386. NULL,
  387. wszREGCAUSEDS,
  388. &varUsingDS);
  389. _JumpIfError(dwRet, Ret, "GetConfigEntry");
  390. CSASSERT ((V_VT(&varUsingDS)== VT_I4));
  391. m_fIsUsingDS = V_I4(&varUsingDS);
  392. Ret:
  393. m_fIsUsingDSKnown = TRUE;
  394. return m_fIsUsingDS;
  395. }
  396. BOOL CertSvrCA::FIsAdvancedServer()
  397. {
  398. HRESULT hr = S_OK;
  399. variant_t var;
  400. ICertAdmin2Ptr pCertAdmin;
  401. CString strCADN, strCALDAP = L"LDAP://";
  402. IADsPtr pADs;
  403. if (!m_fAdvancedServerKnown)
  404. {
  405. hr = m_pParentMachine->GetAdmin2(&pCertAdmin);
  406. if(S_OK==hr)
  407. {
  408. hr = pCertAdmin->GetCAProperty(
  409. m_bstrConfig,
  410. CR_PROP_ADVANCEDSERVER, // PropId
  411. 0, // Index
  412. PROPTYPE_LONG, // PropType
  413. 0, // Flags
  414. &var);
  415. }
  416. if(S_OK != hr)
  417. {
  418. // couldn't figure it out from CA, try DS
  419. DWORD dwFlags;
  420. hr = GetCAFlagsFromDS(&dwFlags);
  421. _JumpIfError(hr, error, "GetCAFlags");
  422. m_fAdvancedServer =
  423. (dwFlags & CA_FLAG_CA_SERVERTYPE_ADVANCED)?
  424. TRUE:
  425. FALSE;
  426. m_fAdvancedServerKnown = TRUE;
  427. }
  428. else
  429. {
  430. CSASSERT ((V_VT(&var)== VT_I4));
  431. m_fAdvancedServer = V_I4(&var);
  432. m_fAdvancedServerKnown = TRUE;
  433. }
  434. _JumpIfError(hr, error, "GetCAProperty");
  435. }
  436. error:
  437. return m_fAdvancedServer;
  438. }
  439. ENUM_CATYPES CertSvrCA::GetCAType()
  440. {
  441. DWORD dwRet;
  442. variant_t varCAType;
  443. if (m_fCATypeKnown)
  444. return m_enumCAType;
  445. dwRet = GetConfigEntry(
  446. NULL,
  447. wszREGCATYPE,
  448. &varCAType);
  449. _JumpIfError(dwRet, Ret, "GetConfigEntry");
  450. CSASSERT ((V_VT(&varCAType)== VT_I4));
  451. m_enumCAType = (ENUM_CATYPES)V_I4(&varCAType);
  452. Ret:
  453. m_fCATypeKnown = TRUE;
  454. return m_enumCAType;
  455. }
  456. BOOL CertSvrCA::FIsIncompleteInstallation()
  457. {
  458. DWORD dwStatus;
  459. if (S_OK == GetSetupStatus(m_strSanitizedName, &dwStatus))
  460. {
  461. if(SETUP_SUSPEND_FLAG & dwStatus)
  462. return TRUE;
  463. }
  464. return FALSE;
  465. }
  466. BOOL CertSvrCA::FIsRequestOutstanding()
  467. {
  468. DWORD dwStatus;
  469. if (S_OK == GetSetupStatus(m_strSanitizedName, &dwStatus))
  470. {
  471. if(SETUP_REQUEST_FLAG & dwStatus)
  472. return TRUE;
  473. }
  474. return FALSE;
  475. }
  476. BOOL CertSvrCA::FDoesSecurityNeedUpgrade()
  477. {
  478. DWORD dwStatus;
  479. if (S_OK == GetSetupStatus(m_strSanitizedName, &dwStatus))
  480. {
  481. if(SETUP_W2K_SECURITY_NOT_UPGRADED_FLAG & dwStatus)
  482. return TRUE;
  483. }
  484. return FALSE;
  485. }
  486. BOOL CertSvrCA::FDoesServerAllowForeignCerts()
  487. {
  488. HRESULT hr;
  489. DWORD dwStatus;
  490. variant_t varKRAFlags;
  491. hr = GetConfigEntry(
  492. NULL,
  493. wszREGKRAFLAGS,
  494. &varKRAFlags);
  495. _JumpIfError(hr, Ret, "GetConfigEntry");
  496. CSASSERT ((V_VT(&varKRAFlags)== VT_I4));
  497. dwStatus = V_I4(&varKRAFlags);
  498. return ((dwStatus & KRAF_ENABLEFOREIGN) != 0);
  499. Ret:
  500. return FALSE;
  501. }
  502. DWORD CertSvrCA::GetCACertByKeyIndex(PCCERT_CONTEXT* ppCertCtxt, int iKeyIndex)
  503. {
  504. // don't cache CA cert
  505. DWORD dwErr;
  506. ICertAdmin2* pCertAdmin = NULL; // must free this!!
  507. VARIANT varPropertyValue;
  508. VariantInit(&varPropertyValue);
  509. *ppCertCtxt = NULL;
  510. dwErr = m_pParentMachine->GetAdmin2(&pCertAdmin);
  511. _JumpIfError(dwErr, Ret, "GetAdmin2");
  512. // To get key's Cert
  513. dwErr = pCertAdmin->GetCAProperty(
  514. m_bstrConfig,
  515. CR_PROP_CASIGCERT, // PropId
  516. iKeyIndex, // PropIndex key index
  517. PROPTYPE_BINARY, // PropType
  518. CR_OUT_BINARY, // Flags
  519. &varPropertyValue);
  520. _JumpIfError(dwErr, Ret, "GetCAProperty");
  521. // varPropertyValue.vt will be VT_BSTR
  522. if (VT_BSTR != varPropertyValue.vt)
  523. {
  524. dwErr = ERROR_INVALID_PARAMETER;
  525. _JumpError(dwErr, Ret, "GetCAProperty");
  526. }
  527. *ppCertCtxt = CertCreateCertificateContext(
  528. CRYPT_ASN_ENCODING,
  529. (PBYTE)varPropertyValue.bstrVal,
  530. SysStringByteLen(varPropertyValue.bstrVal));
  531. if (*ppCertCtxt == NULL)
  532. {
  533. dwErr = GetLastError();
  534. _JumpError(dwErr, Ret, "CertCreateCertContext");
  535. }
  536. dwErr = ERROR_SUCCESS;
  537. Ret:
  538. VariantClear(&varPropertyValue);
  539. if (pCertAdmin)
  540. pCertAdmin->Release();
  541. return dwErr;
  542. }
  543. DWORD CertSvrCA::GetCurrentCRL(PCCRL_CONTEXT* ppCRLCtxt, BOOL fBaseCRL)
  544. {
  545. return GetCRLByKeyIndex(ppCRLCtxt, fBaseCRL, -1);
  546. }
  547. DWORD CertSvrCA::GetCRLByKeyIndex(PCCRL_CONTEXT* ppCRLCtxt, BOOL fBaseCRL, int iKeyIndex)
  548. {
  549. // don't cache CRL
  550. DWORD dwErr;
  551. ICertAdmin2* pCertAdmin = NULL; // must free this!!
  552. VARIANT varPropertyValue;
  553. VariantInit(&varPropertyValue);
  554. *ppCRLCtxt = NULL;
  555. dwErr = m_pParentMachine->GetAdmin2(&pCertAdmin);
  556. _JumpIfError(dwErr, Ret, "GetAdmin2");
  557. // To get each key's BASE CRL
  558. dwErr = pCertAdmin->GetCAProperty(
  559. m_bstrConfig,
  560. fBaseCRL ? CR_PROP_BASECRL : CR_PROP_DELTACRL, // PropId
  561. iKeyIndex, // PropIndex key index
  562. PROPTYPE_BINARY, // PropType
  563. CR_OUT_BINARY, // Flags
  564. &varPropertyValue);
  565. _JumpIfError(dwErr, Ret, "GetCAProperty");
  566. // varPropertyValue.vt will be VT_BSTR
  567. if (VT_BSTR != varPropertyValue.vt)
  568. {
  569. dwErr = ERROR_INVALID_PARAMETER;
  570. _JumpError(dwErr, Ret, "GetCAProperty");
  571. }
  572. *ppCRLCtxt = CertCreateCRLContext(
  573. CRYPT_ASN_ENCODING,
  574. (PBYTE)varPropertyValue.bstrVal,
  575. SysStringByteLen(varPropertyValue.bstrVal));
  576. if (*ppCRLCtxt == NULL)
  577. {
  578. dwErr = GetLastError();
  579. _JumpError(dwErr, Ret, "CertCreateCRLContext");
  580. }
  581. dwErr = ERROR_SUCCESS;
  582. Ret:
  583. VariantClear(&varPropertyValue);
  584. if (pCertAdmin)
  585. pCertAdmin->Release();
  586. return dwErr;
  587. }
  588. HRESULT CertSvrCA::GetConfigEntry(
  589. LPWSTR szConfigSubKey,
  590. LPWSTR szConfigEntry,
  591. VARIANT *pvarOut)
  592. {
  593. HRESULT hr = S_OK;
  594. ICertAdmin2Ptr pAdmin;
  595. LPWSTR pwszLocalMachine = NULL;
  596. CString strConfig = m_pParentMachine->m_strMachineName;
  597. if(m_pParentMachine->m_strMachineName.IsEmpty())
  598. {
  599. hr = myGetMachineDnsName(&pwszLocalMachine);
  600. _JumpIfError(hr, Err, "myGetMachineDnsName");
  601. strConfig = pwszLocalMachine;
  602. }
  603. strConfig += L"\\";
  604. strConfig += m_strSanitizedName;
  605. VariantInit(pvarOut);
  606. hr = m_pParentMachine->GetAdmin2(&pAdmin, true);
  607. _JumpIfError(hr, Err, "GetAdmin2");
  608. hr = pAdmin->GetConfigEntry(
  609. strConfig.GetBuffer(),
  610. szConfigSubKey,
  611. szConfigEntry,
  612. pvarOut);
  613. _JumpIfError2(hr, Err, "GetConfigEntry",
  614. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  615. Err:
  616. LOCAL_FREE(pwszLocalMachine);
  617. return hr;
  618. }
  619. HRESULT CertSvrCA::SetConfigEntry(
  620. LPWSTR szConfigSubKey,
  621. LPWSTR szConfigEntry,
  622. VARIANT *pvarIn)
  623. {
  624. HRESULT hr = S_OK;
  625. ICertAdmin2Ptr pAdmin;
  626. LPWSTR pwszLocalMachine = NULL;
  627. CString strConfig = m_pParentMachine->m_strMachineName;
  628. if(m_pParentMachine->m_strMachineName.IsEmpty())
  629. {
  630. hr = myGetMachineDnsName(&pwszLocalMachine);
  631. _JumpIfError(hr, Err, "myGetMachineDnsName");
  632. strConfig = pwszLocalMachine;
  633. }
  634. strConfig += L"\\";
  635. strConfig += m_strSanitizedName;
  636. hr = m_pParentMachine->GetAdmin2(&pAdmin, true);
  637. _JumpIfError(hr, Err, "GetAdmin2");
  638. hr = pAdmin->SetConfigEntry(
  639. strConfig.GetBuffer(),
  640. szConfigSubKey,
  641. szConfigEntry,
  642. pvarIn);
  643. _JumpIfError(hr, Err, "SetConfigEntry");
  644. Err:
  645. LOCAL_FREE(pwszLocalMachine);
  646. return hr;
  647. }
  648. ////////////////////////////////////////////////////////////////
  649. // CertStor stub
  650. DWORD CertSvrCA::GetRootCertStore(HCERTSTORE* phCertStore)
  651. {
  652. if (m_fRootStoreOpenAttempted)
  653. {
  654. *phCertStore = m_hRootCertStore;
  655. return m_hrRootCertStoreOpen;
  656. }
  657. m_fRootStoreOpenAttempted = TRUE;
  658. LONG dwRet;
  659. CString cstrCertStorePath;
  660. if (! m_pParentMachine->IsLocalMachine())
  661. {
  662. // if remote, prefix with "\\mattt3\"
  663. cstrCertStorePath = m_strServer;
  664. cstrCertStorePath += L"\\";
  665. }
  666. cstrCertStorePath += L"ROOT";
  667. m_hRootCertStore = CertOpenStore(
  668. CERT_STORE_PROV_SYSTEM,
  669. CRYPT_ASN_ENCODING,
  670. NULL, // hCryptProv
  671. CERT_SYSTEM_STORE_LOCAL_MACHINE |
  672. CERT_STORE_OPEN_EXISTING_FLAG |
  673. CERT_STORE_MAXIMUM_ALLOWED_FLAG,
  674. (const void *)(LPCWSTR)cstrCertStorePath);
  675. if (m_hRootCertStore == NULL)
  676. {
  677. dwRet = GetLastError();
  678. _JumpError(dwRet, Ret, "CertOpenStore");
  679. }
  680. dwRet = ERROR_SUCCESS;
  681. Ret:
  682. *phCertStore = m_hRootCertStore;
  683. m_hrRootCertStoreOpen = HRESULT_FROM_WIN32(dwRet);
  684. return dwRet;
  685. }
  686. DWORD CertSvrCA::GetCACertStore(HCERTSTORE* phCertStore)
  687. {
  688. if (m_fCertStoreOpenAttempted)
  689. {
  690. *phCertStore = m_hCACertStore;
  691. return m_hrCACertStoreOpen;
  692. }
  693. m_fCertStoreOpenAttempted = TRUE;
  694. LONG dwRet;
  695. CString cstrCertStorePath;
  696. if (! m_pParentMachine->IsLocalMachine())
  697. {
  698. // if remote, prefix with "\\mattt3\"
  699. cstrCertStorePath = m_strServer;
  700. cstrCertStorePath += L"\\";
  701. }
  702. cstrCertStorePath += wszCA_CERTSTORE;
  703. m_hCACertStore = CertOpenStore(
  704. CERT_STORE_PROV_SYSTEM,
  705. CRYPT_ASN_ENCODING,
  706. NULL, // hCryptProv
  707. CERT_SYSTEM_STORE_LOCAL_MACHINE |
  708. CERT_STORE_OPEN_EXISTING_FLAG |
  709. CERT_STORE_MAXIMUM_ALLOWED_FLAG,
  710. (const void *)(LPCWSTR)cstrCertStorePath);
  711. if (m_hCACertStore == NULL)
  712. {
  713. dwRet = GetLastError();
  714. _JumpError(dwRet, Ret, "CertOpenStore");
  715. }
  716. dwRet = ERROR_SUCCESS;
  717. Ret:
  718. *phCertStore = m_hCACertStore;
  719. m_hrCACertStoreOpen = HRESULT_FROM_WIN32(dwRet);
  720. return dwRet;
  721. }
  722. DWORD CertSvrCA::GetKRACertStore(HCERTSTORE* phCertStore)
  723. {
  724. if (m_fKRAStoreOpenAttempted)
  725. {
  726. *phCertStore = m_hKRACertStore;
  727. return m_hrKRACertStoreOpen;
  728. }
  729. m_fKRAStoreOpenAttempted = TRUE;
  730. LONG dwRet;
  731. CString cstrCertStorePath;
  732. if (! m_pParentMachine->IsLocalMachine())
  733. {
  734. // if remote, prefix with "\\mattt3\"
  735. cstrCertStorePath = m_strServer;
  736. cstrCertStorePath += L"\\";
  737. }
  738. cstrCertStorePath += wszKRA_CERTSTORE;
  739. m_hKRACertStore = CertOpenStore(
  740. CERT_STORE_PROV_SYSTEM,
  741. CRYPT_ASN_ENCODING,
  742. NULL, // hCryptProv
  743. CERT_SYSTEM_STORE_LOCAL_MACHINE|
  744. CERT_STORE_MAXIMUM_ALLOWED_FLAG,
  745. (const void *)(LPCWSTR)cstrCertStorePath);
  746. if (m_hKRACertStore == NULL)
  747. {
  748. dwRet = GetLastError();
  749. _JumpError(dwRet, Ret, "CertOpenStore");
  750. }
  751. dwRet = ERROR_SUCCESS;
  752. Ret:
  753. *phCertStore = m_hKRACertStore;
  754. m_hrKRACertStoreOpen = HRESULT_FROM_WIN32(dwRet);
  755. return dwRet;
  756. }
  757. //////////////////////////
  758. // CertSvrMachine class
  759. CertSvrMachine::CertSvrMachine()
  760. {
  761. m_dwServiceStatus = ERROR_SERVICE_NOT_ACTIVE;
  762. m_hCachedConfigBaseKey = NULL;
  763. m_bAttemptedBaseKeyOpen = FALSE;
  764. m_fLocalIsKnown = FALSE;
  765. m_fIsWhistlerMachine = FALSE;
  766. m_fIsWhistlerMachineKnown = FALSE;
  767. m_cRef = 1; // one "Release()" will initiate clean up
  768. }
  769. CertSvrMachine::~CertSvrMachine()
  770. {
  771. CSASSERT(m_cRef == 0);
  772. // delete any CAs that we still hold on to -- we own this memory
  773. for (int i=0; i<m_CAList.GetSize(); i++)
  774. {
  775. delete m_CAList[i];
  776. }
  777. Init();
  778. }
  779. void CertSvrMachine::Init()
  780. {
  781. // on initialization, caller owns memory contents of m_CAList --
  782. // we no longer do
  783. m_dwServiceStatus = ERROR_SERVICE_NOT_ACTIVE;
  784. if (m_hCachedConfigBaseKey)
  785. {
  786. RegCloseKey(m_hCachedConfigBaseKey);
  787. m_hCachedConfigBaseKey = NULL;
  788. }
  789. m_bAttemptedBaseKeyOpen = FALSE;
  790. // clean other objects
  791. m_CAList.Init(); // scope owns memory
  792. m_strMachineNamePersist.Init();
  793. m_strMachineName.Init();
  794. }
  795. BOOL CertSvrMachine::FIsWhistlerMachine()
  796. {
  797. HRESULT hr = S_OK;
  798. VARIANT varTmp;
  799. VariantInit(&varTmp);
  800. if(!m_fIsWhistlerMachineKnown)
  801. {
  802. hr = GetRootConfigEntry(
  803. wszREGVERSION,
  804. &varTmp);
  805. _JumpIfError(hr, Err, "GetConfigEntry");
  806. DBGPRINT((DBG_SS_INFO, "Found version: 0x%x", V_I4(&varTmp)));
  807. CSASSERT ((V_VT(&varTmp)== VT_I4));
  808. m_fIsWhistlerMachine = (V_I4(&varTmp) >= CSVER_WHISTLER); // bigger than or equal to major Whistler version? return TRUE!
  809. m_fIsWhistlerMachineKnown = TRUE;
  810. }
  811. Err:
  812. VariantClear(&varTmp);
  813. return m_fIsWhistlerMachine;
  814. }
  815. HRESULT CertSvrMachine::GetRootConfigEntry(
  816. LPWSTR szConfigEntry,
  817. VARIANT *pvarOut)
  818. {
  819. HRESULT hr = S_OK;
  820. ICertAdmin2Ptr pAdmin;
  821. LPWSTR pwszLocalMachine = NULL;
  822. CString strConfig = m_strMachineName;
  823. if(m_strMachineName.IsEmpty())
  824. {
  825. hr = myGetMachineDnsName(&pwszLocalMachine);
  826. _JumpIfError(hr, Err, "myGetMachineDnsName");
  827. strConfig = pwszLocalMachine;
  828. }
  829. VariantInit(pvarOut);
  830. hr = GetAdmin2(&pAdmin, true);
  831. _JumpIfError(hr, Err, "GetAdmin2");
  832. hr = pAdmin->GetConfigEntry(
  833. strConfig.GetBuffer(),
  834. NULL,
  835. szConfigEntry,
  836. pvarOut);
  837. _JumpIfError(hr, Err, "GetConfigEntry");
  838. Err:
  839. LOCAL_FREE(pwszLocalMachine);
  840. return hr;
  841. }
  842. HRESULT CertSvrMachine::GetAdmin(ICertAdmin** ppAdmin)
  843. {
  844. HRESULT hr;
  845. BOOL fCoInit = FALSE;
  846. if (!IsCertSvrServiceRunning())
  847. {
  848. *ppAdmin = NULL;
  849. return RPC_S_NOT_LISTENING;
  850. }
  851. // ensure this thread initialized
  852. hr = CoInitialize(NULL);
  853. if ((S_OK == hr) || (S_FALSE == hr))
  854. fCoInit = TRUE;
  855. // create interface, pass back
  856. hr = CoCreateInstance(
  857. CLSID_CCertAdmin,
  858. NULL, // pUnkOuter
  859. CLSCTX_INPROC_SERVER,
  860. IID_ICertAdmin,
  861. (void **) ppAdmin);
  862. _PrintIfError(hr, "CoCreateInstance");
  863. if (fCoInit)
  864. CoUninitialize();
  865. return hr;
  866. }
  867. HRESULT CertSvrMachine::GetAdmin2(
  868. ICertAdmin2** ppAdmin,
  869. bool fIgnoreServiceDown /* = false*/)
  870. {
  871. HRESULT hr = S_OK, hr1;
  872. BOOL fCoInit = FALSE;
  873. if (!fIgnoreServiceDown && !IsCertSvrServiceRunning())
  874. {
  875. *ppAdmin = NULL;
  876. return RPC_S_NOT_LISTENING;
  877. }
  878. hr1 = CoInitialize(NULL);
  879. if ((S_OK == hr1) || (S_FALSE == hr1))
  880. fCoInit = TRUE;
  881. // create interface, pass back
  882. hr = CoCreateInstance(
  883. CLSID_CCertAdmin,
  884. NULL, // pUnkOuter
  885. CLSCTX_INPROC_SERVER,
  886. IID_ICertAdmin2,
  887. (void **) ppAdmin);
  888. _PrintIfError(hr, "CoCreateInstance");
  889. if (fCoInit)
  890. CoUninitialize();
  891. return hr;
  892. }
  893. #define STARTSTOP_MAX_RETRY_SECONDS 30
  894. DWORD CertSvrMachine::CertSvrStartStopService(HWND hwndParent, BOOL fStartSvc)
  895. {
  896. DWORD dwRet;
  897. SC_HANDLE schService = NULL;
  898. SC_HANDLE schSCManager = NULL;
  899. SERVICE_STATUS ServiceStatus;
  900. HANDLE hProgressDlg = NULL;
  901. DWORD dwAttempts = 0;
  902. CWaitCursor cwait;
  903. schSCManager = OpenSCManagerW(
  904. GetNullMachineName(&m_strMachineName),// machine (NULL == local)
  905. NULL, // database (NULL == default)
  906. SC_MANAGER_CONNECT // access required
  907. );
  908. if ( NULL == schSCManager )
  909. {
  910. dwRet = GetLastError();
  911. _JumpError(dwRet, Ret, "OpenSCManagerW");
  912. }
  913. schService = OpenServiceW(
  914. schSCManager,
  915. wszSERVICE_NAME,
  916. ( fStartSvc ? SERVICE_START : SERVICE_STOP ) | SERVICE_QUERY_STATUS
  917. );
  918. if (NULL == schService)
  919. {
  920. dwRet = GetLastError();
  921. _JumpError(dwRet, Ret, "OpenServiceW");
  922. }
  923. // UNDONE: TRY/EXCEPT
  924. hProgressDlg = StartProgressDlg(
  925. g_hInstance,
  926. hwndParent,
  927. STARTSTOP_MAX_RETRY_SECONDS,
  928. 0,
  929. fStartSvc ? IDS_STARTING_SVC : IDS_STOPPING_SVC);
  930. //
  931. // try to start the service
  932. //
  933. if (fStartSvc)
  934. {
  935. if (!StartService( schService, 0, NULL))
  936. {
  937. dwRet = GetLastError();
  938. if (dwRet == ERROR_SERVICE_ALREADY_RUNNING)
  939. dwRet = ERROR_SUCCESS;
  940. _JumpError2(dwRet, Ret, "StartService", ERROR_SUCCESS);
  941. }
  942. }
  943. else
  944. {
  945. if (! ControlService( schService, SERVICE_CONTROL_STOP, &ServiceStatus ) )
  946. {
  947. dwRet = GetLastError();
  948. if (dwRet == ERROR_SERVICE_NOT_ACTIVE)
  949. dwRet = ERROR_SUCCESS;
  950. _JumpError2(dwRet, Ret, "ControlService", ERROR_SUCCESS);
  951. }
  952. }
  953. while( QueryServiceStatus( schService, &ServiceStatus ) )
  954. {
  955. //
  956. // FProgressDlgRunning sets upper time bound on loop
  957. //
  958. if( !FProgressDlgRunning() )
  959. break;
  960. if (fStartSvc)
  961. {
  962. // demorgan's on (pending OR (running AND !pausable))
  963. if ((ServiceStatus.dwCurrentState != (DWORD) SERVICE_START_PENDING) && // not pending AND
  964. ((ServiceStatus.dwCurrentState != (DWORD) SERVICE_RUNNING) || // (not running OR is pausable)
  965. (0 != (ServiceStatus.dwControlsAccepted & (DWORD) SERVICE_ACCEPT_PAUSE_CONTINUE) )) )
  966. break;
  967. }
  968. else
  969. {
  970. if (ServiceStatus.dwCurrentState != (DWORD) SERVICE_STOP_PENDING)
  971. break;
  972. }
  973. Sleep( 500 );
  974. }
  975. if ( ServiceStatus.dwCurrentState != (DWORD)(fStartSvc ? SERVICE_RUNNING : SERVICE_STOPPED))
  976. {
  977. dwRet = ServiceStatus.dwWin32ExitCode;
  978. if (ERROR_SERVICE_SPECIFIC_ERROR == dwRet)
  979. dwRet = ServiceStatus.dwServiceSpecificExitCode;
  980. _JumpError(dwRet, Ret, "ServiceStatus.dwServiceSpecificExitCode");
  981. }
  982. dwRet = ERROR_SUCCESS;
  983. Ret:
  984. if (hProgressDlg)
  985. EndProgressDlg(hProgressDlg);
  986. if (schService)
  987. CloseServiceHandle(schService);
  988. if (schSCManager)
  989. CloseServiceHandle(schSCManager);
  990. if (ERROR_SUCCESS == dwRet)
  991. m_dwServiceStatus = ServiceStatus.dwCurrentState;
  992. else
  993. m_dwServiceStatus = SERVICE_STOPPED;
  994. return dwRet;
  995. }
  996. DWORD CertSvrMachine::RefreshServiceStatus()
  997. {
  998. DWORD dwRet;
  999. SC_HANDLE schService = NULL;
  1000. SC_HANDLE schSCManager = NULL;
  1001. SERVICE_STATUS ServiceStatus;
  1002. HCURSOR hPrevCur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  1003. m_dwServiceStatus = 0;
  1004. schSCManager = OpenSCManagerW(
  1005. GetNullMachineName(&m_strMachineName),// machine (NULL == local)
  1006. NULL, // database (NULL == default)
  1007. SC_MANAGER_CONNECT // access required
  1008. );
  1009. if ( NULL == schSCManager )
  1010. {
  1011. dwRet = GetLastError();
  1012. _JumpError(dwRet, Ret, "OpenSCManagerW");
  1013. }
  1014. schService = OpenServiceW(
  1015. schSCManager,
  1016. wszSERVICE_NAME,
  1017. SERVICE_INTERROGATE
  1018. );
  1019. if (NULL == schService)
  1020. {
  1021. dwRet = GetLastError();
  1022. _JumpError(dwRet, Ret, "OpenServiceW");
  1023. }
  1024. if (!ControlService(schService, SERVICE_CONTROL_INTERROGATE, &ServiceStatus) )
  1025. {
  1026. dwRet = GetLastError();
  1027. if (dwRet != ERROR_SERVICE_NOT_ACTIVE)
  1028. {
  1029. _JumpError(dwRet, Ret, "ControlService");
  1030. }
  1031. }
  1032. m_dwServiceStatus = ServiceStatus.dwCurrentState;
  1033. dwRet = ERROR_SUCCESS;
  1034. Ret:
  1035. SetCursor(hPrevCur);
  1036. if (schService)
  1037. CloseServiceHandle(schService);
  1038. if (schSCManager)
  1039. CloseServiceHandle(schSCManager);
  1040. return dwRet;
  1041. }
  1042. LPCWSTR CertSvrMachine::GetCaCommonNameAtPos(DWORD iPos)
  1043. {
  1044. // if (iPos > (m_cCAList-1))
  1045. if (iPos > (DWORD)m_CAList.GetUpperBound())
  1046. return NULL;
  1047. return GetCaAtPos(iPos)->m_strCommonName;
  1048. }
  1049. CertSvrCA* CertSvrMachine::GetCaAtPos(DWORD iPos)
  1050. {
  1051. // if (iPos > (m_cCAList-1))
  1052. if (iPos > (DWORD)m_CAList.GetUpperBound())
  1053. return NULL;
  1054. return m_CAList[iPos];
  1055. // return m_rgpCAList[iPos];
  1056. }
  1057. DWORD CertSvrMachine::PrepareData(HWND hwndParent)
  1058. {
  1059. // hwndParent: we will display a dlg describing what we're waiting for
  1060. HANDLE hDlg = NULL;
  1061. DWORD dwRet;
  1062. __try
  1063. {
  1064. CSASSERT(hwndParent);
  1065. hDlg = StartProgressDlg(g_hInstance, hwndParent, 10, 0, IDS_CA_REDISCOVER); // don't time out
  1066. dwRet = RefreshServiceStatus();
  1067. _LeaveIfError(dwRet, "RefreshServiceStatus");
  1068. dwRet = RetrieveCertSvrCAs(0);
  1069. _LeaveIfError(dwRet, "RetrieveCertSvrCAs");
  1070. }
  1071. __finally
  1072. {
  1073. if (hDlg)
  1074. EndProgressDlg(hDlg);
  1075. }
  1076. return dwRet;
  1077. }
  1078. #include "csdisp.h"
  1079. LPWSTR szConfigFieldDescription[] =
  1080. {
  1081. L"Server",
  1082. L"CommonName",
  1083. L"OrgUnit",
  1084. L"Organization",
  1085. L"Locality",
  1086. L"State",
  1087. L"Country",
  1088. L"Config",
  1089. L"Comment",
  1090. };
  1091. DWORD
  1092. CertSvrMachine::RetrieveCertSvrCAs(
  1093. IN DWORD Flags)
  1094. {
  1095. HRESULT hr;
  1096. LONG i, iEntries;
  1097. LONG count=0, Index;
  1098. LPWSTR szTargetMachine = NULL;
  1099. LPWSTR szTargetMachine2 = NULL;
  1100. WCHAR* szRegActive; // no delete;
  1101. LPWSTR pwszzCAList = NULL;
  1102. ICertAdmin2Ptr pAdmin;
  1103. LPWSTR pwszSanitizedName = NULL;
  1104. LPWSTR pwszCAList = NULL;
  1105. size_t len;
  1106. bool fNameIsAlreadySanitized = false;
  1107. DWORD dwVersion;
  1108. // init var containing machine sans whacks
  1109. Index = sizeof(szTargetMachine);
  1110. if (!m_strMachineName.IsEmpty())
  1111. {
  1112. const WCHAR* pch = (LPCWSTR)m_strMachineName;
  1113. // skip whack whack
  1114. if ((pch[0] == '\\') && (pch[1] == '\\'))
  1115. pch+=2;
  1116. szTargetMachine = (LPWSTR)LocalAlloc(LPTR, WSZ_BYTECOUNT(pch));
  1117. _JumpIfOutOfMemory(hr, error, szTargetMachine);
  1118. wcscpy(szTargetMachine, pch);
  1119. }
  1120. else
  1121. {
  1122. hr = myGetComputerNames(&szTargetMachine, &szTargetMachine2);
  1123. _JumpIfError(hr, error, "myGetComputerNames");
  1124. }
  1125. // Don't go to DS for this, just RegConnect
  1126. // DS would give us: strConfig, szMachine, and Template info.
  1127. // we already can derive strConfig, szMachine; we weren't using template info here
  1128. // look for CAs that aren't yet completely set up
  1129. do
  1130. {
  1131. HKEY hBaseKey; // this is cached
  1132. DWORD cbOut, dwType;
  1133. hr = myPingCertSrv(
  1134. szTargetMachine,
  1135. NULL,
  1136. &pwszzCAList,
  1137. NULL,
  1138. NULL,
  1139. &dwVersion,
  1140. NULL);
  1141. if(S_OK==hr)
  1142. {
  1143. if(dwVersion<2)
  1144. hr = HRESULT_FROM_WIN32(ERROR_OLD_WIN_VERSION);
  1145. _JumpIfError(hr, error, "Whistler CA snapin cannot connect to older CAs");
  1146. }
  1147. // If for any reason we couldn't ping the CA, fail over to
  1148. // registry; we currently support only one CA per machine, if this
  1149. // changes in the future, replace the code below with an enumeration
  1150. // of nodes under configuration regkey.
  1151. if(S_OK!=hr)
  1152. {
  1153. hr = myGetCertRegValue(
  1154. szTargetMachine,
  1155. NULL,
  1156. NULL,
  1157. NULL,
  1158. wszREGACTIVE,
  1159. (BYTE**)&pwszCAList,
  1160. NULL,
  1161. &dwType);
  1162. _JumpIfError(hr, error, "myGetCertRegValue");
  1163. CSASSERT(dwType==REG_SZ);
  1164. len = wcslen(pwszCAList)+1;
  1165. pwszzCAList = (LPWSTR)LocalAlloc(LMEM_FIXED, (len+1)*sizeof(WCHAR));
  1166. _JumpIfAllocFailed(pwszzCAList, error);
  1167. wcscpy(pwszzCAList, pwszCAList);
  1168. pwszzCAList[len] = L'\0';
  1169. // regactive gives us already sanitized ca name
  1170. fNameIsAlreadySanitized = true;
  1171. }
  1172. _JumpIfError(hr, error, "myPingCertSrv");
  1173. szRegActive = pwszzCAList;
  1174. while (szRegActive[0] != '\0') // while we don't hit end-of-string
  1175. {
  1176. for (int ii=0; ii<m_CAList.GetSize(); ii++)
  1177. {
  1178. // Common name match? break early
  1179. if (m_CAList[ii]->m_strCommonName.IsEqual(szRegActive))
  1180. break;
  1181. }
  1182. // not found?
  1183. if (ii == m_CAList.GetSize())
  1184. {
  1185. // and insert it into the list
  1186. CertSvrCA* pIssuer = new CertSvrCA(this);
  1187. _JumpIfOutOfMemory(hr, error, pIssuer);
  1188. pIssuer->m_strServer = szTargetMachine;
  1189. if(!fNameIsAlreadySanitized)
  1190. {
  1191. hr = mySanitizeName(szRegActive, &pwszSanitizedName);
  1192. _JumpIfError(hr, error, "mySanitizeName");
  1193. pIssuer->m_strSanitizedName = pwszSanitizedName;
  1194. }
  1195. else
  1196. {
  1197. pIssuer->m_strSanitizedName = szRegActive;
  1198. }
  1199. LPWSTR pszString = NULL;
  1200. DWORD cbString = 0;
  1201. variant_t varCommonName;
  1202. // get prettified common name
  1203. hr = pIssuer->GetConfigEntry(
  1204. NULL,
  1205. wszREGCOMMONNAME,
  1206. &varCommonName);
  1207. _JumpIfError(hr, error, "GetConfigEntry");
  1208. if (V_VT(&varCommonName)!=VT_BSTR ||
  1209. V_BSTR(&varCommonName)==NULL)
  1210. {
  1211. hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  1212. _JumpError(hr, error, "GetConfigEntry");
  1213. }
  1214. pIssuer->m_strCommonName = V_BSTR(&varCommonName);
  1215. varCommonName.Clear();
  1216. // config is common name (not sanitized)
  1217. pIssuer->m_strConfig = szTargetMachine;
  1218. pIssuer->m_strConfig += L"\\";
  1219. pIssuer->m_strConfig += pIssuer->m_strCommonName;
  1220. // Last: get description if exists
  1221. if (S_OK == pIssuer->GetConfigEntry(
  1222. NULL,
  1223. wszREGCADESCRIPTION,
  1224. &varCommonName))
  1225. {
  1226. if (V_VT(&varCommonName)==VT_BSTR &&
  1227. V_BSTR(&varCommonName)!=NULL)
  1228. {
  1229. pIssuer->m_strComment = V_BSTR(&varCommonName);
  1230. }
  1231. }
  1232. // create oft-used bstr
  1233. pIssuer->m_bstrConfig = pIssuer->m_strConfig.AllocSysString();
  1234. _JumpIfOutOfMemory(hr, error, pIssuer->m_bstrConfig);
  1235. m_CAList.Add(pIssuer);
  1236. }
  1237. // REG_MULTI_SZ: fwd to next string
  1238. szRegActive += wcslen(szRegActive)+1;
  1239. }
  1240. } while(0);
  1241. error:
  1242. LOCAL_FREE(pwszzCAList);
  1243. LOCAL_FREE(pwszSanitizedName);
  1244. LOCAL_FREE(pwszCAList);
  1245. if (szTargetMachine)
  1246. LocalFree(szTargetMachine);
  1247. if (szTargetMachine2)
  1248. LocalFree(szTargetMachine2);
  1249. return(hr);
  1250. }
  1251. STDMETHODIMP
  1252. CertSvrMachine::Load(IStream *pStm)
  1253. {
  1254. CSASSERT(pStm);
  1255. HRESULT hr;
  1256. // no header magic ?
  1257. // Read the string
  1258. hr = CStringLoad(m_strMachineNamePersist, pStm);
  1259. m_strMachineName = m_strMachineNamePersist;
  1260. if (FAILED(hr))
  1261. return E_FAIL;
  1262. return S_OK;
  1263. }
  1264. STDMETHODIMP
  1265. CertSvrMachine::Save(IStream *pStm, BOOL fClearDirty)
  1266. {
  1267. CSASSERT(pStm);
  1268. HRESULT hr;
  1269. // no header magic ?
  1270. // save the string
  1271. hr = CStringSave(m_strMachineNamePersist, pStm, fClearDirty);
  1272. _PrintIfError(hr, "CStringSave");
  1273. // Verify that the write operation succeeded
  1274. if (FAILED(hr))
  1275. return STG_E_CANTSAVE;
  1276. return S_OK;
  1277. }
  1278. STDMETHODIMP CertSvrMachine::GetSizeMax(int *pcbSize)
  1279. {
  1280. CSASSERT(pcbSize);
  1281. *pcbSize = (m_strMachineNamePersist.GetLength()+1)* sizeof(WCHAR);
  1282. return S_OK;
  1283. }