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.

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