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.

7544 lines
203 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: setuput.cpp
  8. //
  9. // Contents: Utility functions for OCM based setup.
  10. //
  11. // History: 04/20/97 JerryK Created
  12. //
  13. //-------------------------------------------------------------------------
  14. #include "pch.cpp"
  15. #pragma hdrstop
  16. // ** C Runtime Includes
  17. #include <sys/types.h>
  18. #include <sys/stat.h>
  19. // ** System Includes **
  20. #include <lmaccess.h>
  21. #include <lmapibuf.h>
  22. #include "csdisp.h"
  23. #include <shlobj.h>
  24. #include <userenv.h>
  25. #include <dsgetdc.h>
  26. #include <sddl.h>
  27. #include <winldap.h>
  28. #include <autoenr.h>
  29. #include <userenvp.h> // CreateLinkFile API
  30. // ** security includes **
  31. #include <aclapi.h>
  32. // ** Application Includes **
  33. #include "initcert.h"
  34. #include "cscsp.h"
  35. #include "cspenum.h"
  36. #include "csldap.h"
  37. #include "wizpage.h"
  38. #include "websetup.h"
  39. #include "certsrvd.h"
  40. #include "regd.h"
  41. #include "usecert.h"
  42. #include "certmsg.h"
  43. #include "dssetup.h"
  44. #include "progress.h"
  45. #include <certca.h>
  46. #include "csprop.h"
  47. #include "setupids.h"
  48. #define __dwFILE__ __dwFILE_OCMSETUP_SETUPUT_CPP__
  49. EXTERN_C const IID IID_IGPEInformation;
  50. EXTERN_C const CLSID CLSID_GPESnapIn;
  51. #define CERT_HALF_SECOND 500 // # of milliseconds in half second
  52. #define CERT_MAX_ATTEMPT 2 * 60 * 2 // # of half seconds in 2 minutes
  53. #define wszREQUESTVERINDPROGID L"CertSrv.Request"
  54. #define wszREQUESTPROGID L"CertSrv.Request.1"
  55. #define wszADMINVERINDPROGID L"CertSrv.Admin"
  56. #define wszADMINPROGID L"CertSrv.Admin.1"
  57. #define wszREQUESTFRIENDLYNAME L"CertSrv Request"
  58. #define wszADMINFRIENDLYNAME L"CertSrv Admin"
  59. #define wszCERTSRV L"CertSrv"
  60. #define wszREGW3SCRIPTMAP L"System\\CurrentControlSet\\Services\\W3SVC\\Parameters\\Script Map"
  61. #define wszHTTPS L"https://"
  62. #define wszASPEXT L".asp"
  63. #define wszHTTP L"http://"
  64. #define wszDOTCERTEXT L".cer"
  65. #define wszNEWLINE L"\n"
  66. #define wszFILESC L"file://\\\\"
  67. #define SZ_REGSVR32 L"regsvr32.exe"
  68. #define SZ_REGSVR32_CERTCLI L"/i:i /n /s certcli.dll"
  69. #define SZ_VERB_OPEN L"open"
  70. // hardcoded shares
  71. #define wszCERTENROLLURLPATH L"/CertEnroll/"
  72. #define wszzREGSUBJECTTEMPLATEVALUE \
  73. wszPROPEMAIL L"\0" \
  74. wszPROPCOMMONNAME L"\0" \
  75. wszATTRORGUNIT4 L"\0" \
  76. wszPROPORGANIZATION L"\0" \
  77. wszPROPLOCALITY L"\0" \
  78. wszPROPSTATE L"\0" \
  79. wszPROPDOMAINCOMPONENT L"\0" \
  80. wszPROPCOUNTRY L"\0"
  81. // Whistler SMIME extension (or any other CSP):
  82. // SMIME Capabilities
  83. // [1]SMIME Capability
  84. // Object ID=1.2.840.113549.3.2 szOID_RSA_RC2CBC, 128 bit
  85. // Parameters=02 02 00 80
  86. // [2]SMIME Capability
  87. // Object ID=1.2.840.113549.3.4 szOID_RSA_RC4, 128 bit
  88. // Parameters=02 02 00 80
  89. // [3]SMIME Capability
  90. // Object ID=1.3.14.3.2.7 szOID_OIWSEC_desCBC
  91. // [4]SMIME Capability
  92. // Object ID=1.2.840.113549.3.7 szOID_RSA_DES_EDE3_CBC
  93. //
  94. #define wszzREGVALUEDEFAULTSMIME \
  95. TEXT(szOID_RSA_RC2CBC) L",128" L"\0" \
  96. TEXT(szOID_RSA_RC4) L",128" L"\0" \
  97. TEXT(szOID_OIWSEC_desCBC) L"\0" \
  98. TEXT(szOID_RSA_DES_EDE3_CBC) L"\0"
  99. #ifdef CERTSRV_ENABLE_ALL_REGISTRY_DEFAULTS
  100. # define wszREGSUBJECTALTNAMEVALUE L"EMail"
  101. # define wszREGSUBJECTALTNAME2VALUE L"EMail"
  102. #else
  103. # define wszREGSUBJECTALTNAMEVALUE \
  104. L"DISABLED: Set to EMail to set SubjectAltName extension to the email address"
  105. # define wszREGSUBJECTALTNAME2VALUE \
  106. L"DISABLED: Set to EMail to set SubjectAltName2 extension to the email address"
  107. #endif
  108. #define szNULL_SESSION_REG_LOCATION "System\\CurrentControlSet\\Services\\LanmanServer\\Parameters"
  109. #define szNULL_SESSION_VALUE "NullSessionPipes"
  110. #define wszDEFAULTSHAREDFOLDER L"\\CAConfig"
  111. // globals
  112. WCHAR *g_pwszArgvPath = NULL; // for installing from local directory
  113. WCHAR *g_pwszNoService = NULL; // skip CreateService
  114. WCHAR *g_pwszSanitizedChar = NULL; // take first char for sanitizing test
  115. #if DBG_CERTSRV
  116. WCHAR *g_pwszDumpStrings = NULL; // dump resource strings
  117. #endif
  118. BOOL g_fW3SvcRunning = FALSE;
  119. WCHAR g_wszServicePath[MAX_PATH];
  120. // Version-independent ProgID
  121. // ProgID
  122. WCHAR const g_wszCertAdmDotDll[] = L"certadm.dll";
  123. WCHAR const g_wszCertCliDotDll[] = L"certcli.dll";
  124. WCHAR const g_wszcertEncDotDll[] = L"certenc.dll";
  125. WCHAR const g_wszCertXDSDotDll[] = L"certxds.dll";
  126. WCHAR const g_wszCertIfDotDll[] = L"certif.dll";
  127. WCHAR const g_wszCertPDefDotDll[] = L"certpdef.dll";
  128. WCHAR const g_wszCertMMCDotDll[] = L"certmmc.dll";
  129. WCHAR const g_wszCertSrvDotMsc[] = L"certsrv.msc";
  130. WCHAR const g_wszSCrdEnrlDotDll[] = L"scrdenrl.dll";
  131. WCHAR const g_wszCertReqDotExe[] = L"certreq.exe";
  132. WCHAR const g_wszCertUtilDotExe[] = L"certutil.exe";
  133. WCHAR const g_wszCertDBDotDll[] = L"certdb.dll";
  134. WCHAR const g_wszCertViewDotDll[] = L"certview.dll";
  135. WCHAR const g_wszCSBullDotGif[] = L"csbull.gif";
  136. WCHAR const g_wszCSBackDotGif[] = L"csback.gif";
  137. WCHAR const g_wszCSLogoDotGif[] = L"cslogo.gif";
  138. CHAR const * const aszRegisterServer[] = {
  139. "DllRegisterServer",
  140. "DllUnregisterServer",
  141. };
  142. typedef struct _REGISTERDLL
  143. {
  144. WCHAR const *pwszDllName;
  145. DWORD Flags;
  146. } REGISTERDLL;
  147. #define RD_SERVER 0x00000001 // Register on server
  148. #define RD_CLIENT 0x00000002 // Register on client
  149. #define RD_UNREGISTER 0x00000004 // Unegister on client & server
  150. #define RD_WHISTLER 0x00000008 // Register must succeed on Whistler only
  151. #define RD_SKIPUNREGPOLICY 0x00000010 // not unreg custom policy during upgrade
  152. #define RD_SKIPUNREGEXIT 0x00000020 // not unreg custom exit during upgrade
  153. #define RD_SKIPUNREGMMC 0x00000040 // bug# 38876
  154. REGISTERDLL const g_aRegisterDll[] = {
  155. { g_wszCertAdmDotDll, RD_SERVER | RD_CLIENT },
  156. { g_wszCertCliDotDll, RD_SERVER | RD_CLIENT },
  157. { g_wszcertEncDotDll, RD_SERVER | RD_CLIENT | RD_UNREGISTER },
  158. { g_wszCertXDSDotDll, RD_SERVER | RD_UNREGISTER | RD_SKIPUNREGEXIT},
  159. { g_wszCertIfDotDll, RD_UNREGISTER },
  160. { g_wszCertPDefDotDll, RD_SERVER | RD_UNREGISTER | RD_SKIPUNREGPOLICY },
  161. { g_wszCertMMCDotDll, RD_SERVER | RD_UNREGISTER | RD_SKIPUNREGMMC },
  162. { g_wszSCrdEnrlDotDll, RD_SERVER | RD_CLIENT | RD_UNREGISTER | RD_WHISTLER },
  163. { g_wszCertDBDotDll, RD_SERVER | RD_UNREGISTER },
  164. { g_wszCertViewDotDll, RD_UNREGISTER },
  165. { NULL, 0 }
  166. };
  167. typedef struct _PROGRAMENTRY
  168. {
  169. UINT uiLinkName;
  170. UINT uiGroupName;
  171. UINT uiDescription;
  172. DWORD csidl; // special folder index
  173. WCHAR const *pwszExeName;
  174. WCHAR const *pwszClientArgs;
  175. WCHAR const *pwszServerArgs;
  176. DWORD Flags;
  177. } PROGRAMENTRY;
  178. #define PE_SERVER 0x00000001 // Install on server
  179. #define PE_CLIENT 0x00000002 // Install on client
  180. #define PE_DELETEONLY 0x00000004 // Always delete
  181. PROGRAMENTRY const g_aProgramEntry[] = {
  182. {
  183. IDS_STARTMENU_NEWCRL_LINKNAME, // uiLinkName
  184. IDS_STARTMENU_CERTSERVER, // uiGroupName
  185. 0, // uiDescription
  186. CSIDL_COMMON_PROGRAMS, // "All Users\Start Menu\Programs"
  187. g_wszCertUtilDotExe, // pwszExeName
  188. NULL, // pwszClientArgs
  189. L"-crl -", // pwszServerArgs
  190. PE_DELETEONLY | PE_SERVER, // Flags
  191. },
  192. {
  193. IDS_STARTMENU_CERTHIER_LINKNAME, // uiLinkName
  194. IDS_STARTMENU_CERTSERVER, // uiGroupName
  195. 0, // uiDescription
  196. CSIDL_COMMON_PROGRAMS, // "All Users\Start Menu\Programs"
  197. L"certhier.exe", // pwszExeName
  198. NULL, // pwszClientArgs
  199. NULL, // pwszServerArgs
  200. PE_DELETEONLY | PE_SERVER, // Flags
  201. },
  202. {
  203. IDS_STARTMENU_CERTREQ_LINKNAME, // uiLinkName
  204. IDS_STARTMENU_CERTSERVER, // uiGroupName
  205. 0, // uiDescription
  206. CSIDL_COMMON_PROGRAMS, // "All Users\Start Menu\Programs"
  207. g_wszCertReqDotExe, // pwszExeName
  208. NULL, // pwszClientArgs
  209. NULL, // pwszServerArgs
  210. PE_DELETEONLY | PE_CLIENT | PE_SERVER, // Flags
  211. },
  212. };
  213. #define CPROGRAMENTRY ARRAYSIZE(g_aProgramEntry)
  214. static char rgcCERT_NULL_SESSION[] = {0x43, 0x45, 0x52, 0x54, 0x00, 0x00};
  215. // ** Prototypes **
  216. HRESULT
  217. UpgradeServerRegEntries(
  218. IN HWND hwnd,
  219. IN PER_COMPONENT_DATA *pComp);
  220. HRESULT
  221. CreateServerRegEntries(
  222. IN HWND hwnd,
  223. IN BOOL fUpgrade,
  224. IN PER_COMPONENT_DATA *pComp);
  225. HRESULT
  226. CreateWebClientRegEntries(
  227. BOOL fUpgrade,
  228. PER_COMPONENT_DATA *pComp);
  229. HRESULT
  230. UpgradeWebClientRegEntries(
  231. PER_COMPONENT_DATA *pComp);
  232. HRESULT
  233. GetServerNames(
  234. IN HWND hwnd,
  235. IN HINSTANCE hInstance,
  236. IN BOOL fUnattended,
  237. OUT WCHAR **ppwszServerName,
  238. OUT WCHAR **ppwszServerNameOld);
  239. HRESULT
  240. UpdateDomainAndUserName(
  241. IN HWND hwnd,
  242. IN OUT PER_COMPONENT_DATA *pComp);
  243. HRESULT
  244. RegisterAndUnRegisterDLLs(
  245. IN DWORD Flags,
  246. IN PER_COMPONENT_DATA *pComp,
  247. IN HWND hwnd);
  248. HRESULT RenameMiscTargets(HWND hwnd, PER_COMPONENT_DATA *pComp, BOOL fServer);
  249. HRESULT DeleteProgramGroups(IN BOOL fAll, IN PER_COMPONENT_DATA *pComp);
  250. HRESULT CreateCertificateService(PER_COMPONENT_DATA *pComp, HWND hwnd);
  251. HRESULT DeleteCertificates(const WCHAR *, BOOL fRoot);
  252. HRESULT TriggerAutoenrollment();
  253. //endproto
  254. #ifdef DBG_OCM_TRACE
  255. VOID
  256. CaptureStackBackTrace(
  257. EXCEPTION_POINTERS *pep,
  258. ULONG cSkip,
  259. ULONG cFrames,
  260. ULONG *aeip)
  261. {
  262. ZeroMemory(aeip, cFrames * sizeof(aeip[0]));
  263. #if i386 == 1
  264. ULONG ieip, *pebp;
  265. ULONG *pebpMax = (ULONG *) MAXLONG; // 2 * 1024 * 1024 * 1024; // 2 gig - 1
  266. ULONG *pebpMin = (ULONG *) (64 * 1024); // 64k
  267. if (pep == NULL)
  268. {
  269. ieip = 0;
  270. cSkip++; // always skip current frame
  271. pebp = ((ULONG *) &pep) - 2;
  272. }
  273. else
  274. {
  275. ieip = 1;
  276. CSASSERT(cSkip == 0);
  277. aeip[0] = pep->ContextRecord->Eip;
  278. pebp = (ULONG *) pep->ContextRecord->Ebp;
  279. }
  280. if (pebp >= pebpMin && pebp < pebpMax)
  281. {
  282. __try
  283. {
  284. for ( ; ieip < cSkip + cFrames; ieip++)
  285. {
  286. if (ieip >= cSkip)
  287. {
  288. aeip[ieip - cSkip] = *(pebp + 1); // save an eip
  289. }
  290. ULONG *pebpNext = (ULONG *) *pebp;
  291. if (pebpNext < pebp + 2 || pebpNext >= pebpMax - 1)
  292. {
  293. break;
  294. }
  295. pebp = pebpNext;
  296. }
  297. }
  298. __except(EXCEPTION_EXECUTE_HANDLER)
  299. {
  300. ;
  301. }
  302. }
  303. #endif // i386 == 1
  304. }
  305. #endif // DBG_OCM_TRACE
  306. VOID
  307. DumpBackTrace(char const *pszName)
  308. {
  309. #ifdef DBG_OCM_TRACE
  310. ULONG aeip[10];
  311. DBGPRINT((MAXDWORD, "%hs: BackTrace:\n", pszName));
  312. CaptureStackBackTrace(NULL, 1, ARRAYSIZE(aeip), aeip);
  313. for (int i = 0; i < ARRAYSIZE(aeip); i++)
  314. {
  315. if (NULL == aeip[i])
  316. {
  317. break;
  318. }
  319. DBGPRINT((MAXDWORD, "ln %x;", aeip[i]));
  320. }
  321. DBGPRINT((MAXDWORD, "\n"));
  322. #endif // DBG_OCM_TRACE
  323. }
  324. __inline VOID
  325. AppendBackSlash(
  326. IN OUT WCHAR *pwszOut)
  327. {
  328. DWORD cwc = wcslen(pwszOut);
  329. if (0 == cwc || L'\\' != pwszOut[cwc - 1])
  330. {
  331. pwszOut[cwc++] = L'\\';
  332. pwszOut[cwc] = L'\0';
  333. }
  334. }
  335. __inline VOID
  336. StripBackSlash(
  337. IN OUT WCHAR *pwszOut)
  338. {
  339. DWORD cwc = wcslen(pwszOut);
  340. if (0 < cwc && L'\\' == pwszOut[cwc - 1])
  341. {
  342. pwszOut[cwc] = L'\0';
  343. }
  344. }
  345. VOID
  346. BuildPath(
  347. OUT WCHAR *pwszOut,
  348. IN DWORD cwcOut,
  349. IN WCHAR const *pwszDir,
  350. IN WCHAR const *pwszFile)
  351. {
  352. wcscpy(pwszOut, pwszDir);
  353. AppendBackSlash(pwszOut);
  354. wcscat(pwszOut, pwszFile);
  355. StripBackSlash(pwszOut);
  356. CSASSERT(wcslen(pwszOut) < cwcOut);
  357. DBGPRINT((DBG_SS_CERTOCMI, "BuildPath(%ws, %ws) -> %ws\n", pwszDir, pwszFile, pwszOut));
  358. }
  359. VOID
  360. FreeCARequestInfo(CASERVERSETUPINFO *pServer)
  361. {
  362. if (NULL != pServer->pwszRequestFile)
  363. {
  364. LocalFree(pServer->pwszRequestFile);
  365. }
  366. if (NULL != pServer->pwszParentCAMachine)
  367. {
  368. LocalFree(pServer->pwszParentCAMachine);
  369. }
  370. if (NULL != pServer->pwszParentCAName)
  371. {
  372. LocalFree(pServer->pwszParentCAName);
  373. }
  374. }
  375. VOID
  376. FreeCAStoreInfo(CASERVERSETUPINFO *pServer)
  377. {
  378. if (NULL != pServer->pwszSharedFolder)
  379. {
  380. LocalFree(pServer->pwszSharedFolder);
  381. }
  382. if (NULL != pServer->pwszDBDirectory)
  383. {
  384. LocalFree(pServer->pwszDBDirectory);
  385. }
  386. if (NULL != pServer->pwszLogDirectory)
  387. {
  388. LocalFree(pServer->pwszLogDirectory);
  389. }
  390. }
  391. VOID
  392. FreeCAServerAdvanceInfo(CASERVERSETUPINFO *pServer)
  393. {
  394. if (NULL != pServer->pCSPInfoList)
  395. {
  396. FreeCSPInfoList(pServer->pCSPInfoList);
  397. }
  398. if (NULL != pServer->pKeyList)
  399. {
  400. csiFreeKeyList(pServer->pKeyList);
  401. }
  402. if (NULL != pServer->pDefaultCSPInfo)
  403. {
  404. freeCSPInfo(pServer->pDefaultCSPInfo);
  405. }
  406. if (NULL != pServer->pwszDesanitizedKeyContainerName)
  407. {
  408. LocalFree(pServer->pwszDesanitizedKeyContainerName);
  409. }
  410. if (NULL != pServer->pccExistingCert)
  411. {
  412. ClearExistingCertToUse(pServer);
  413. }
  414. if (NULL != pServer->pccUpgradeCert)
  415. {
  416. CertFreeCertificateContext(pServer->pccUpgradeCert);
  417. }
  418. if (NULL != pServer->pwszValidityPeriodCount)
  419. {
  420. LocalFree(pServer->pwszValidityPeriodCount);
  421. }
  422. if (NULL != pServer->pszAlgId)
  423. {
  424. LocalFree(pServer->pszAlgId);
  425. }
  426. if (NULL != pServer->hMyStore)
  427. {
  428. CertCloseStore(pServer->hMyStore, 0);
  429. }
  430. // don't free following because they are just pointers
  431. // pServer->pCSPInfo
  432. // pServer->pHashInfo
  433. }
  434. VOID
  435. FreeCAServerIdInfo(
  436. CASERVERSETUPINFO *pServer)
  437. {
  438. if (NULL != pServer->pwszCACommonName)
  439. {
  440. LocalFree(pServer->pwszCACommonName);
  441. pServer->pwszCACommonName = NULL;
  442. }
  443. }
  444. VOID
  445. FreeCAServerInfo(CASERVERSETUPINFO *pServer)
  446. {
  447. FreeCAServerIdInfo(pServer);
  448. FreeCAServerAdvanceInfo(pServer);
  449. FreeCAStoreInfo(pServer);
  450. FreeCARequestInfo(pServer);
  451. if (NULL != pServer->pwszSanitizedName)
  452. {
  453. LocalFree(pServer->pwszSanitizedName);
  454. }
  455. if (NULL != pServer->pwszDNSuffix)
  456. {
  457. LocalFree(pServer->pwszDNSuffix);
  458. }
  459. if (NULL != pServer->pwszFullCADN)
  460. {
  461. LocalFree(pServer->pwszFullCADN);
  462. }
  463. if (NULL != pServer->pwszKeyContainerName)
  464. {
  465. LocalFree(pServer->pwszKeyContainerName);
  466. }
  467. if (NULL != pServer->pwszCACertFile)
  468. {
  469. LocalFree(pServer->pwszCACertFile);
  470. }
  471. if (NULL != pServer->pwszUseExistingCert)
  472. {
  473. LocalFree(pServer->pwszUseExistingCert);
  474. }
  475. if (NULL != pServer->pwszPreserveDB)
  476. {
  477. LocalFree(pServer->pwszPreserveDB);
  478. }
  479. if (NULL != pServer->pwszCustomPolicy)
  480. {
  481. LocalFree(pServer->pwszCustomPolicy);
  482. }
  483. if (NULL != pServer->pwszzCustomExit)
  484. {
  485. LocalFree(pServer->pwszzCustomExit);
  486. }
  487. }
  488. VOID
  489. FreeCAClientInfo(CAWEBCLIENTSETUPINFO *pClient)
  490. {
  491. if (NULL != pClient)
  492. {
  493. if (NULL != pClient->pwszWebCAMachine)
  494. {
  495. LocalFree(pClient->pwszWebCAMachine);
  496. }
  497. if (NULL != pClient->pwszWebCAName)
  498. {
  499. LocalFree(pClient->pwszWebCAName);
  500. }
  501. if (NULL != pClient->pwszSanitizedWebCAName)
  502. {
  503. LocalFree(pClient->pwszSanitizedWebCAName);
  504. }
  505. if (NULL != pClient->pwszSharedFolder)
  506. {
  507. LocalFree(pClient->pwszSharedFolder);
  508. }
  509. }
  510. }
  511. VOID
  512. FreeCAInfo(CASETUPINFO *pCA)
  513. {
  514. if (NULL != pCA->pServer)
  515. {
  516. FreeCAServerInfo(pCA->pServer);
  517. LocalFree(pCA->pServer);
  518. pCA->pServer = NULL;
  519. }
  520. if (NULL != pCA->pClient)
  521. {
  522. FreeCAClientInfo(pCA->pClient);
  523. LocalFree(pCA->pClient);
  524. pCA->pClient = NULL;
  525. }
  526. }
  527. VOID
  528. FreeCAComponentInfo(PER_COMPONENT_DATA *pComp)
  529. {
  530. if (NULL != pComp->pwszCustomMessage)
  531. {
  532. LocalFree(pComp->pwszCustomMessage);
  533. }
  534. if (NULL != pComp->pwszComponent)
  535. {
  536. LocalFree(pComp->pwszComponent);
  537. }
  538. if (NULL != pComp->pwszUnattendedFile)
  539. {
  540. LocalFree(pComp->pwszUnattendedFile);
  541. }
  542. if (NULL != pComp->pwszServerName)
  543. {
  544. LocalFree(pComp->pwszServerName);
  545. }
  546. if (NULL != pComp->pwszServerNameOld)
  547. {
  548. LocalFree(pComp->pwszServerNameOld);
  549. }
  550. if (NULL != pComp->pwszSystem32)
  551. {
  552. LocalFree(pComp->pwszSystem32);
  553. }
  554. FreeCAInfo(&(pComp->CA));
  555. }
  556. VOID
  557. FreeCAGlobals(VOID)
  558. {
  559. if (NULL != g_pwszArgvPath)
  560. {
  561. LocalFree(g_pwszArgvPath);
  562. }
  563. if (NULL != g_pwszNoService)
  564. {
  565. LocalFree(g_pwszNoService);
  566. }
  567. if (NULL != g_pwszSanitizedChar)
  568. {
  569. LocalFree(g_pwszSanitizedChar);
  570. }
  571. #if DBG_CERTSRV
  572. if (NULL != g_pwszDumpStrings)
  573. {
  574. LocalFree(g_pwszDumpStrings);
  575. }
  576. #endif
  577. }
  578. VOID
  579. SaveCustomMessage(
  580. IN OUT PER_COMPONENT_DATA *pComp,
  581. OPTIONAL IN WCHAR const *pwszCustomMessage)
  582. {
  583. HRESULT hr;
  584. if (NULL != pwszCustomMessage)
  585. {
  586. if (NULL != pComp->pwszCustomMessage)
  587. {
  588. LocalFree(pComp->pwszCustomMessage);
  589. pComp->pwszCustomMessage = NULL;
  590. }
  591. hr = myDupString(pwszCustomMessage, &pComp->pwszCustomMessage);
  592. _JumpIfError(hr, error, "myDupString");
  593. }
  594. error:
  595. ;
  596. }
  597. HRESULT
  598. LoadDefaultCAIDAttributes(
  599. IN OUT PER_COMPONENT_DATA *pComp)
  600. {
  601. HRESULT hr;
  602. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  603. DWORD i;
  604. // free existing Id info before load default
  605. FreeCAServerIdInfo(pServer);
  606. // load default from resource
  607. if (NULL != g_pwszSanitizedChar)
  608. {
  609. if (NULL != pServer->pwszCACommonName)
  610. {
  611. LocalFree(pServer->pwszCACommonName);
  612. }
  613. // replace with the env var
  614. pServer->pwszCACommonName = (WCHAR*)LocalAlloc(LMEM_FIXED,
  615. (wcslen(g_pwszSanitizedChar) + 1) * sizeof(WCHAR));
  616. _JumpIfOutOfMemory(hr, error, pServer->pwszCACommonName);
  617. wcscpy(pServer->pwszCACommonName, g_pwszSanitizedChar);
  618. }
  619. // default validity
  620. pServer->enumValidityPeriod = dwVALIDITYPERIODENUMDEFAULT;
  621. pServer->dwValidityPeriodCount = dwVALIDITYPERIODCOUNTDEFAULT_ROOT;
  622. GetSystemTimeAsFileTime(&pServer->NotBefore);
  623. pServer->NotAfter = pServer->NotBefore;
  624. myMakeExprDateTime(
  625. &pServer->NotAfter,
  626. pServer->dwValidityPeriodCount,
  627. pServer->enumValidityPeriod);
  628. hr = S_OK;
  629. error:
  630. return(hr);
  631. }
  632. HRESULT
  633. GetDefaultDBDirectory(
  634. IN PER_COMPONENT_DATA *pComp,
  635. OUT WCHAR **ppwszDir)
  636. {
  637. HRESULT hr;
  638. DWORD cwc;
  639. *ppwszDir = NULL;
  640. cwc = wcslen(pComp->pwszSystem32) +
  641. wcslen(wszLOGPATH) +
  642. 1;
  643. *ppwszDir = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
  644. _JumpIfOutOfMemory(hr, error, *ppwszDir);
  645. // default
  646. wcscpy(*ppwszDir, pComp->pwszSystem32);
  647. wcscat(*ppwszDir, wszLOGPATH);
  648. CSASSERT(cwc == (DWORD) (wcslen(*ppwszDir) + 1));
  649. hr = S_OK;
  650. error:
  651. return(hr);
  652. }
  653. HRESULT
  654. LoadDefaultDBDirAttributes(
  655. IN OUT PER_COMPONENT_DATA *pComp)
  656. {
  657. HRESULT hr;
  658. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  659. if (NULL != pServer->pwszDBDirectory)
  660. {
  661. LocalFree(pServer->pwszDBDirectory);
  662. pServer->pwszDBDirectory = NULL;
  663. }
  664. hr = GetDefaultDBDirectory(pComp, &pServer->pwszDBDirectory);
  665. _JumpIfError(hr, error, "GetDefaultDBDirectory");
  666. // default log dir is the same as db
  667. if (NULL != pServer->pwszLogDirectory)
  668. {
  669. LocalFree(pServer->pwszLogDirectory);
  670. }
  671. pServer->pwszLogDirectory = (WCHAR *) LocalAlloc(
  672. LMEM_FIXED,
  673. (wcslen(pServer->pwszDBDirectory) + 1) * sizeof(WCHAR));
  674. _JumpIfOutOfMemory(hr, error, pServer->pwszLogDirectory);
  675. wcscpy(pServer->pwszLogDirectory, pServer->pwszDBDirectory);
  676. pServer->fPreserveDB = FALSE;
  677. hr = S_OK;
  678. error:
  679. return(hr);
  680. }
  681. HRESULT
  682. LoadDefaultAdvanceAttributes(
  683. IN OUT CASERVERSETUPINFO* pServer)
  684. {
  685. HRESULT hr;
  686. // load default csp, ms base csp
  687. pServer->fAdvance = FALSE;
  688. if (NULL == pServer->pDefaultCSPInfo)
  689. {
  690. pServer->pDefaultCSPInfo = newCSPInfo(PROV_RSA_FULL, wszBASECSP);
  691. if (NULL == pServer->pDefaultCSPInfo && !IsWhistler())
  692. {
  693. pServer->pDefaultCSPInfo = newCSPInfo(PROV_RSA_FULL, MS_DEF_PROV_W);
  694. }
  695. _JumpIfOutOfMemory(hr, error, pServer->pDefaultCSPInfo);
  696. }
  697. // determine default hash, sha1
  698. pServer->pDefaultHashInfo = pServer->pDefaultCSPInfo->pHashList;
  699. while (NULL != pServer->pDefaultHashInfo)
  700. {
  701. if (pServer->pDefaultHashInfo->idAlg == CALG_SHA1)
  702. {
  703. //got default
  704. break;
  705. }
  706. pServer->pDefaultHashInfo = pServer->pDefaultHashInfo->next;
  707. }
  708. // If we have not just created a default key, reset the key container name.
  709. if (pServer->pCSPInfo != pServer->pDefaultCSPInfo ||
  710. (pServer->dwKeyLength != CA_DEFAULT_KEY_LENGTH_ROOT &&
  711. pServer->dwKeyLength != CA_DEFAULT_KEY_LENGTH_SUB) ||
  712. !pServer->fDeletableNewKey) {
  713. ClearKeyContainerName(pServer);
  714. }
  715. // ok, point to defaults
  716. pServer->pCSPInfo = pServer->pDefaultCSPInfo;
  717. pServer->pHashInfo = pServer->pDefaultHashInfo;
  718. // some other related defaults
  719. pServer->dwKeyLength = IsRootCA(pServer->CAType)?
  720. CA_DEFAULT_KEY_LENGTH_ROOT:
  721. CA_DEFAULT_KEY_LENGTH_SUB;
  722. pServer->dwKeyLenMin = 0;
  723. pServer->dwKeyLenMax = 0;
  724. // update hash oid
  725. if (NULL != pServer->pszAlgId)
  726. {
  727. // free old
  728. LocalFree(pServer->pszAlgId);
  729. }
  730. hr = myGetSigningOID(
  731. NULL, // hProv
  732. pServer->pCSPInfo->pwszProvName,
  733. pServer->pCSPInfo->dwProvType,
  734. pServer->pHashInfo->idAlg,
  735. &(pServer->pszAlgId));
  736. _JumpIfError(hr, error, "myGetSigningOID");
  737. error:
  738. return(hr);
  739. }
  740. HRESULT
  741. LoadDefaultCAClientAttributes(
  742. IN HWND hwnd,
  743. IN OUT PER_COMPONENT_DATA *pComp)
  744. {
  745. HRESULT hr;
  746. CAWEBCLIENTSETUPINFO *pClient = pComp->CA.pClient;
  747. if (NULL != pClient)
  748. {
  749. // free existing client setup info
  750. FreeCAClientInfo(pClient);
  751. LocalFree(pClient);
  752. pComp->CA.pClient = NULL;
  753. }
  754. pComp->CA.pClient = (CAWEBCLIENTSETUPINFO *) LocalAlloc(
  755. LMEM_FIXED | LMEM_ZEROINIT,
  756. sizeof(CAWEBCLIENTSETUPINFO));
  757. _JumpIfOutOfMemory(hr, error, pComp->CA.pClient);
  758. pComp->CA.pClient->WebCAType = ENUM_UNKNOWN_CA;
  759. hr = S_OK;
  760. error:
  761. return(hr);
  762. }
  763. HRESULT
  764. GetDefaultSharedFolder(
  765. OUT WCHAR **ppwszSharedFolder)
  766. {
  767. HRESULT hr = S_OK;
  768. WCHAR *pwszSysDrive = NULL;
  769. *ppwszSharedFolder = NULL;
  770. hr = myGetEnvString(&pwszSysDrive, L"SystemDrive");
  771. if (S_OK == hr)
  772. {
  773. *ppwszSharedFolder = (WCHAR *) LocalAlloc(
  774. LMEM_FIXED,
  775. (wcslen(pwszSysDrive) + wcslen(wszDEFAULTSHAREDFOLDER) + 1) *
  776. sizeof(WCHAR));
  777. _JumpIfOutOfMemory(hr, error, *ppwszSharedFolder);
  778. wcscpy(*ppwszSharedFolder, pwszSysDrive);
  779. wcscat(*ppwszSharedFolder, wszDEFAULTSHAREDFOLDER);
  780. }
  781. error:
  782. if (NULL != pwszSysDrive)
  783. {
  784. LocalFree(pwszSysDrive);
  785. }
  786. return hr;
  787. }
  788. HRESULT
  789. LoadDefaultCAServerAttributes(
  790. IN HWND hwnd,
  791. IN OUT PER_COMPONENT_DATA *pComp)
  792. {
  793. HRESULT hr;
  794. BOOL fDSCA = FALSE;
  795. WCHAR *pwszSysDrive = NULL;
  796. bool fIsDomainMember;
  797. bool fUserCanInstallCA;
  798. if (NULL != pComp->CA.pServer)
  799. {
  800. // free existing server setup info
  801. FreeCAServerInfo(pComp->CA.pServer);
  802. LocalFree(pComp->CA.pServer);
  803. }
  804. // allocate server info buffer
  805. pComp->CA.pServer = (CASERVERSETUPINFO *) LocalAlloc(
  806. LMEM_FIXED | LMEM_ZEROINIT,
  807. sizeof(CASERVERSETUPINFO));
  808. _JumpIfOutOfMemory(hr, error, pComp->CA.pServer);
  809. hr = LoadDefaultCAIDAttributes(pComp);
  810. _JumpIfError(hr, error, "LoadDefaultCAIDAttributes");
  811. hr = LoadDefaultAdvanceAttributes(pComp->CA.pServer);
  812. _JumpIfError(hr, error, "LoadDefaultAdvanceAttributes");
  813. hr = LoadDefaultDBDirAttributes(pComp);
  814. _JumpIfError(hr, error, "LoadDefaultDBDirAttributes");
  815. // decide default using DS
  816. // xtan, the following call should be replaced with HasDSWritePermission()
  817. // remove DisableEnterpriseCAs()
  818. pComp->CA.pServer->fUseDS = FALSE;
  819. hr = LocalMachineIsDomainMember(&fIsDomainMember);
  820. _JumpIfError(hr, error, "LocalMachineIsDomainMember");
  821. if (fIsDomainMember)
  822. {
  823. if(IsDSAvailable())
  824. {
  825. hr = CurrentUserCanInstallCA(fUserCanInstallCA);
  826. _JumpIfError(hr, error, "CurrentUserCanInstallCA");
  827. if(fUserCanInstallCA)
  828. {
  829. pComp->CA.pServer->fUseDS = TRUE;
  830. fDSCA = csiIsAnyDSCAAvailable();
  831. }
  832. }
  833. }
  834. // alway free and null old shared folder
  835. if (NULL != pComp->CA.pServer->pwszSharedFolder)
  836. {
  837. LocalFree(pComp->CA.pServer->pwszSharedFolder);
  838. pComp->CA.pServer->pwszSharedFolder = NULL;
  839. }
  840. // decide default CA type and default shared folder
  841. pComp->CA.pServer->CAType = ENUM_STANDALONE_ROOTCA;
  842. if (pComp->CA.pServer->fUseDS)
  843. {
  844. if (fDSCA)
  845. {
  846. pComp->CA.pServer->CAType = ENUM_ENTERPRISE_SUBCA;
  847. }
  848. else
  849. {
  850. pComp->CA.pServer->CAType = ENUM_ENTERPRISE_ROOTCA;
  851. }
  852. }
  853. if (pComp->fUnattended || !pComp->CA.pServer->fUseDS)
  854. {
  855. BOOL fChangeToDefault = FALSE;
  856. // try reg load first
  857. hr = myGetCertRegStrValue(
  858. NULL,
  859. NULL,
  860. NULL,
  861. wszREGDIRECTORY,
  862. &pComp->CA.pServer->pwszSharedFolder);
  863. if (S_OK != hr && HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  864. {
  865. _JumpErrorStr(hr, error, "myGetCertRegStrValue", wszREGDIRECTORY);
  866. }
  867. if (S_OK == hr)
  868. {
  869. if (L'\0' == *pComp->CA.pServer->pwszSharedFolder)
  870. {
  871. // this mast be empty string
  872. fChangeToDefault = TRUE;
  873. }
  874. else
  875. {
  876. //got something, make sure unc path exist
  877. DWORD dwPathFlag;
  878. if (!myIsFullPath(pComp->CA.pServer->pwszSharedFolder,
  879. &dwPathFlag))
  880. {
  881. // somehow register an invalid path, don't use it
  882. fChangeToDefault = TRUE;
  883. }
  884. else
  885. {
  886. if (UNC_PATH == dwPathFlag &&
  887. DE_DIREXISTS != DirExists(pComp->CA.pServer->pwszSharedFolder))
  888. {
  889. // this unc path doesn't exist any more
  890. // not making any sense to use it
  891. fChangeToDefault = TRUE;
  892. pComp->CA.pServer->fUNCPathNotFound = TRUE;
  893. }
  894. }
  895. }
  896. }
  897. else
  898. {
  899. //must be not found
  900. fChangeToDefault = TRUE;
  901. }
  902. if (fChangeToDefault)
  903. {
  904. //free 1st
  905. if (NULL != pComp->CA.pServer->pwszSharedFolder)
  906. {
  907. LocalFree(pComp->CA.pServer->pwszSharedFolder);
  908. }
  909. // load default
  910. hr = GetDefaultSharedFolder(&pComp->CA.pServer->pwszSharedFolder);
  911. _JumpIfError(hr, error, "GetDefaultSharedFolder");
  912. }
  913. }
  914. pComp->CA.pServer->fSaveRequestAsFile = FALSE;
  915. pComp->CA.pServer->pwszRequestFile = NULL;
  916. pComp->CA.pServer->pwszParentCAMachine = NULL;
  917. pComp->CA.pServer->pwszParentCAName = NULL;
  918. hr = S_OK;
  919. error:
  920. return hr;
  921. }
  922. HRESULT
  923. InitCASetup(
  924. IN HWND hwnd,
  925. IN OUT PER_COMPONENT_DATA *pComp)
  926. {
  927. HRESULT hr;
  928. UINT ui;
  929. bool fIsAdmin = false;
  930. hr = GetServerNames(
  931. hwnd,
  932. pComp->hInstance,
  933. pComp->fUnattended,
  934. &pComp->pwszServerName,
  935. &pComp->pwszServerNameOld);
  936. _JumpIfError(hr, error, "GetServerNames");
  937. DBGPRINT((
  938. DBG_SS_CERTOCMI,
  939. "InitCASetup:GetServerNames:%ws,%ws\n",
  940. pComp->pwszServerName,
  941. pComp->pwszServerNameOld));
  942. DumpBackTrace("InitCASetup");
  943. hr = IsCurrentUserBuiltinAdmin(&fIsAdmin);
  944. _JumpIfError(hr, error, "IsCurrentUserBuiltinAdmin");
  945. if (!fIsAdmin)
  946. {
  947. hr = E_ACCESSDENIED;
  948. CertErrorMessageBox(
  949. pComp->hInstance,
  950. pComp->fUnattended,
  951. hwnd,
  952. IDS_ERR_NOT_ADM,
  953. 0,
  954. NULL);
  955. _JumpError(hr, error, "IsCurrentUserBuiltinAdmin");
  956. }
  957. // load some of environment variables
  958. hr = myGetEnvString(&g_pwszArgvPath, L"CertSrv_BinDir");
  959. hr = myGetEnvString(&g_pwszNoService, L"CertSrv_NoService");
  960. hr = myGetEnvString(&g_pwszSanitizedChar, L"CertSrv_Sanitize");
  961. #if DBG_CERTSRV
  962. myGetEnvString(&g_pwszDumpStrings, L"CertSrv_DumpStrings");
  963. #endif
  964. // figure out where the system root directory is (build path to x:\\winnt\system32\)
  965. ui = GetSystemDirectory(NULL, 0); // returns chars neccessary to hold path (incl null)
  966. if (ui == 0)
  967. {
  968. hr = myHLastError();
  969. _JumpError(hr, error, "GetSystemDirectory");
  970. }
  971. pComp->pwszSystem32 = (LPWSTR)LocalAlloc(LMEM_FIXED, (ui+1)*sizeof(WCHAR));
  972. if (NULL == pComp->pwszSystem32)
  973. {
  974. hr = E_OUTOFMEMORY;
  975. _JumpError(hr, error, "LocalAlloc");
  976. }
  977. if (0 == GetSystemDirectory(pComp->pwszSystem32, ui))
  978. {
  979. hr = myHLastError();
  980. _JumpError(hr, error, "GetSystemDirectory");
  981. }
  982. wcscat(pComp->pwszSystem32, L"\\");
  983. // load default atrributes anyway
  984. hr = LoadDefaultCAServerAttributes(hwnd, pComp);
  985. _JumpIfError(hr, error, "LoadDefaultCAServerAttributes");
  986. hr = LoadDefaultCAClientAttributes(hwnd, pComp);
  987. _JumpIfError(hr, error, "LoadDefaultCAClientAttributes");
  988. if (pComp->fUnattended)
  989. {
  990. // hook unattended data
  991. hr = HookUnattendedServerAttributes(pComp,
  992. LookupSubComponent(cscServer));
  993. _JumpIfError(hr, error, "HookUnattendedServerAttributes");
  994. hr = HookUnattendedClientAttributes(pComp,
  995. LookupSubComponent(cscClient));
  996. _JumpIfError(hr, error, "HookUnattendedClientAttributes");
  997. }
  998. hr = S_OK;
  999. error:
  1000. return(hr);
  1001. }
  1002. HRESULT
  1003. CreateInitialCertificateRequest(
  1004. IN HCRYPTPROV hProv,
  1005. IN CASERVERSETUPINFO *pServer,
  1006. IN PER_COMPONENT_DATA *pComp,
  1007. IN HWND hwnd,
  1008. OUT BYTE **ppbEncode,
  1009. OUT DWORD *pcbEncode)
  1010. {
  1011. HRESULT hr;
  1012. BYTE *pbSubjectEncoded = NULL;
  1013. DWORD cbSubjectEncoded;
  1014. HINF hInf = INVALID_HANDLE_VALUE;
  1015. DWORD ErrorLine;
  1016. LPCWSTR pszErrorPtr;
  1017. hr = AddCNAndEncode(
  1018. pServer->pwszCACommonName,
  1019. pServer->pwszDNSuffix,
  1020. &pbSubjectEncoded,
  1021. &cbSubjectEncoded);
  1022. _JumpIfError(hr, error, "AddCNAndEncodeCertStrToName");
  1023. hr = myInfOpenFile(NULL, &hInf, &ErrorLine);
  1024. _PrintIfError2(
  1025. hr,
  1026. "myInfOpenFile",
  1027. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  1028. hr = csiBuildRequest(
  1029. hInf,
  1030. NULL,
  1031. pbSubjectEncoded,
  1032. cbSubjectEncoded,
  1033. pServer->pszAlgId,
  1034. TRUE, // fNewKey
  1035. CANAMEIDTOICERT(pServer->dwCertNameId),
  1036. CANAMEIDTOIKEY(pServer->dwCertNameId),
  1037. hProv,
  1038. hwnd,
  1039. pComp->hInstance,
  1040. pComp->fUnattended,
  1041. ppbEncode,
  1042. pcbEncode);
  1043. _JumpIfError(hr, error, "csiBuildRequest");
  1044. error:
  1045. if (INVALID_HANDLE_VALUE != hInf)
  1046. {
  1047. myInfCloseFile(hInf);
  1048. }
  1049. if (NULL != pbSubjectEncoded)
  1050. {
  1051. myFree(pbSubjectEncoded, CERTLIB_USE_LOCALALLOC);
  1052. }
  1053. CSILOG(hr, IDS_LOG_CREATE_REQUEST, NULL, NULL, NULL);
  1054. return(hr);
  1055. }
  1056. HRESULT
  1057. BuildCAHierarchy(
  1058. HCRYPTPROV hProv,
  1059. PER_COMPONENT_DATA *pComp,
  1060. CRYPT_KEY_PROV_INFO const *pKeyProvInfo,
  1061. HWND hwnd)
  1062. {
  1063. HRESULT hr;
  1064. BYTE *pbRequest = NULL;
  1065. DWORD cbRequest;
  1066. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  1067. BSTR bStrChain = NULL;
  1068. if (!pServer->fSaveRequestAsFile)
  1069. {
  1070. // online case
  1071. if (NULL == pServer->pwszParentCAMachine ||
  1072. NULL == pServer->pwszParentCAName)
  1073. {
  1074. hr = E_POINTER;
  1075. _JumpError(hr, error, "Empty machine name or parent ca name");
  1076. }
  1077. }
  1078. // create request 1st
  1079. hr = CreateInitialCertificateRequest(
  1080. hProv,
  1081. pServer,
  1082. pComp,
  1083. hwnd,
  1084. &pbRequest,
  1085. &cbRequest);
  1086. if (S_OK != hr)
  1087. {
  1088. pComp->iErrMsg = IDS_ERR_BUILDCERTREQUEST;
  1089. _JumpError(hr, error, "CreateInitialCertificateRequest");
  1090. }
  1091. // save it to a file always
  1092. hr = EncodeToFileW(
  1093. pServer->pwszRequestFile,
  1094. pbRequest,
  1095. cbRequest,
  1096. DECF_FORCEOVERWRITE | CRYPT_STRING_BASE64REQUESTHEADER);
  1097. _JumpIfError(hr, error, "EncodeToFileW");
  1098. // register request file name always
  1099. hr = mySetCARegFileNameTemplate(
  1100. wszREGREQUESTFILENAME,
  1101. pComp->pwszServerName,
  1102. pServer->pwszSanitizedName,
  1103. pServer->pwszRequestFile);
  1104. _JumpIfErrorStr(hr, error, "mySetCARegFileNameTemplate", wszREGREQUESTFILENAME);
  1105. if (pServer->fSaveRequestAsFile)
  1106. {
  1107. // mark it as request file
  1108. hr = SetSetupStatus(
  1109. pServer->pwszSanitizedName,
  1110. SETUP_SUSPEND_FLAG | SETUP_REQUEST_FLAG,
  1111. TRUE);
  1112. _JumpIfError(hr, error, "SetSetupStatus");
  1113. // done if save as request file
  1114. goto done;
  1115. }
  1116. hr = csiSubmitCARequest(
  1117. pComp->hInstance,
  1118. pComp->fUnattended,
  1119. hwnd,
  1120. FALSE, // fRenew
  1121. FALSE, // fRetrievePending
  1122. pServer->pwszSanitizedName,
  1123. pServer->pwszParentCAMachine,
  1124. pServer->pwszParentCAName,
  1125. pbRequest,
  1126. cbRequest,
  1127. &bStrChain);
  1128. // in any case, you can finish setup from mmc
  1129. _JumpIfError(hr, done, "csiSubmitCARequest");
  1130. hr = csiFinishInstallationFromPKCS7(
  1131. pComp->hInstance,
  1132. pComp->fUnattended,
  1133. hwnd,
  1134. pServer->pwszSanitizedName,
  1135. pServer->pwszCACommonName,
  1136. pKeyProvInfo,
  1137. pServer->CAType,
  1138. CANAMEIDTOICERT(pServer->dwCertNameId),
  1139. CANAMEIDTOIKEY(pServer->dwCertNameId),
  1140. pServer->fUseDS,
  1141. FALSE, // fRenew
  1142. pComp->pwszServerName,
  1143. (BYTE *) bStrChain,
  1144. SysStringByteLen(bStrChain),
  1145. pServer->pwszCACertFile);
  1146. _JumpIfError(hr, error, "csiFinishInstallationFromPKCS7");
  1147. done:
  1148. hr = S_OK;
  1149. error:
  1150. if (NULL != pbRequest)
  1151. {
  1152. myFree(pbRequest, CERTLIB_USE_LOCALALLOC);
  1153. }
  1154. if (NULL != bStrChain)
  1155. {
  1156. SysFreeString(bStrChain);
  1157. }
  1158. return(hr);
  1159. }
  1160. // Find the newest CA cert that:
  1161. // - matches the passed Subject DN,
  1162. // - matches the passed cert index,
  1163. // - expires prior the next newer cert (compare to pNotAfter)
  1164. // - expires latest of all that match the above
  1165. // - has KeyProvInfo
  1166. // - key and cert can be used together to sign
  1167. HRESULT
  1168. SetCARegOldCertHashByIndex(
  1169. IN WCHAR const *pwszSanitizedName,
  1170. IN HCERTSTORE hStore,
  1171. IN WCHAR const *pwszDN,
  1172. IN DWORD iCert,
  1173. IN OUT FILETIME *pNotAfter)
  1174. {
  1175. HRESULT hr;
  1176. CERT_CONTEXT const *pCert = NULL;
  1177. CERT_CONTEXT const *pCertNewest = NULL;
  1178. WCHAR *pwszDNT = NULL;
  1179. DWORD dwProvType;
  1180. WCHAR *pwszProvName = NULL;
  1181. ALG_ID idAlg;
  1182. BOOL fMachineKeyset;
  1183. DWORD dwNameId;
  1184. DWORD cbKey;
  1185. CRYPT_KEY_PROV_INFO *pKey = NULL;
  1186. hr = myGetCertSrvCSP(
  1187. FALSE, // fEncryptionCSP
  1188. pwszSanitizedName,
  1189. &dwProvType,
  1190. &pwszProvName,
  1191. &idAlg,
  1192. &fMachineKeyset,
  1193. NULL); // pdwKeySize
  1194. _JumpIfError(hr, error, "myGetCertSrvCSP");
  1195. while (TRUE)
  1196. {
  1197. if (NULL != pKey)
  1198. {
  1199. LocalFree(pKey);
  1200. pKey = NULL;
  1201. }
  1202. if (NULL != pwszDNT)
  1203. {
  1204. LocalFree(pwszDNT);
  1205. pwszDNT = NULL;
  1206. }
  1207. pCert = CertEnumCertificatesInStore(hStore, pCert);
  1208. if (NULL == pCert)
  1209. {
  1210. break;
  1211. }
  1212. hr = myCertNameToStr(
  1213. X509_ASN_ENCODING,
  1214. &pCert->pCertInfo->Subject,
  1215. CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
  1216. &pwszDNT);
  1217. if (S_OK != hr)
  1218. {
  1219. _PrintError(hr, "myCertNameToStr");
  1220. continue;
  1221. }
  1222. if (0 != lstrcmp(pwszDN, pwszDNT))
  1223. {
  1224. DBGPRINT((DBG_SS_CERTOCM, "Skipping cert: %ws\n", pwszDNT));
  1225. continue;
  1226. }
  1227. hr = myGetNameId(pCert, &dwNameId);
  1228. if (S_OK != hr ||
  1229. MAXDWORD == dwNameId ||
  1230. CANAMEIDTOICERT(dwNameId) != iCert)
  1231. {
  1232. DBGPRINT((DBG_SS_CERTOCM, "Skipping cert: NameId=%x\n", dwNameId));
  1233. continue;
  1234. }
  1235. DBGPRINT((DBG_SS_CERTOCM, "NameId=%x\n", dwNameId));
  1236. if (0 < CompareFileTime(&pCert->pCertInfo->NotAfter, pNotAfter))
  1237. {
  1238. DBGPRINT((DBG_SS_CERTOCM, "Skipping cert: too new\n"));
  1239. continue;
  1240. }
  1241. if (!myCertGetCertificateContextProperty(
  1242. pCert,
  1243. CERT_KEY_PROV_INFO_PROP_ID,
  1244. CERTLIB_USE_LOCALALLOC,
  1245. (VOID **) &pKey,
  1246. &cbKey))
  1247. {
  1248. hr = myHLastError();
  1249. _PrintError(hr, "CertGetCertificateContextProperty");
  1250. continue;
  1251. }
  1252. hr = myValidateHashForSigning(
  1253. pKey->pwszContainerName,
  1254. pwszProvName,
  1255. dwProvType,
  1256. fMachineKeyset,
  1257. &pCert->pCertInfo->SubjectPublicKeyInfo,
  1258. idAlg);
  1259. if (S_OK != hr)
  1260. {
  1261. _PrintError(hr, "myValidateHashForSigning");
  1262. continue;
  1263. }
  1264. if (NULL != pCertNewest)
  1265. {
  1266. if (0 > CompareFileTime(
  1267. &pCert->pCertInfo->NotAfter,
  1268. &pCertNewest->pCertInfo->NotAfter))
  1269. {
  1270. DBGPRINT((DBG_SS_CERTOCM, "Skipping cert: not newest\n"));
  1271. continue;
  1272. }
  1273. CertFreeCertificateContext(pCertNewest);
  1274. pCertNewest = NULL;
  1275. }
  1276. pCertNewest = CertDuplicateCertificateContext(pCert);
  1277. if (NULL == pCertNewest)
  1278. {
  1279. hr = myHLastError();
  1280. _JumpError(hr, error, "CertDuplicateCertificate");
  1281. }
  1282. }
  1283. if (NULL == pCertNewest)
  1284. {
  1285. hr = CRYPT_E_NOT_FOUND;
  1286. _JumpError(hr, error, "CertEnumCertificatesInStore");
  1287. }
  1288. // mark as unarchived:
  1289. CertSetCertificateContextProperty(
  1290. pCertNewest,
  1291. CERT_ARCHIVED_PROP_ID,
  1292. 0,
  1293. NULL);
  1294. hr = mySetCARegHash(pwszSanitizedName, CSRH_CASIGCERT, iCert, pCertNewest);
  1295. _JumpIfError(hr, error, "mySetCARegHash");
  1296. *pNotAfter = pCertNewest->pCertInfo->NotAfter;
  1297. error:
  1298. if (NULL != pKey)
  1299. {
  1300. LocalFree(pKey);
  1301. }
  1302. if (NULL != pwszDNT)
  1303. {
  1304. LocalFree(pwszDNT);
  1305. }
  1306. if (NULL != pwszProvName)
  1307. {
  1308. LocalFree(pwszProvName);
  1309. }
  1310. if (NULL != pCertNewest)
  1311. {
  1312. CertFreeCertificateContext(pCertNewest);
  1313. }
  1314. if (NULL != pCert)
  1315. {
  1316. CertFreeCertificateContext(pCert);
  1317. }
  1318. return(hr);
  1319. }
  1320. HRESULT
  1321. SetCARegOldCertHashes(
  1322. IN WCHAR const *pwszSanitizedName,
  1323. IN DWORD cCertOld,
  1324. IN CERT_CONTEXT const *pccCA)
  1325. {
  1326. HRESULT hr;
  1327. HCERTSTORE hMyStore = NULL;
  1328. DWORD i;
  1329. WCHAR *pwszDN = NULL;
  1330. FILETIME NotAfter;
  1331. if (0 != cCertOld)
  1332. {
  1333. hr = myCertNameToStr(
  1334. X509_ASN_ENCODING,
  1335. &pccCA->pCertInfo->Subject,
  1336. CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
  1337. &pwszDN);
  1338. _JumpIfError(hr, error, "myCertNameToStr");
  1339. // open my store
  1340. hMyStore = CertOpenStore(
  1341. CERT_STORE_PROV_SYSTEM_W,
  1342. X509_ASN_ENCODING,
  1343. NULL, // hProv
  1344. CERT_SYSTEM_STORE_LOCAL_MACHINE |
  1345. CERT_STORE_ENUM_ARCHIVED_FLAG,
  1346. wszMY_CERTSTORE);
  1347. if (NULL == hMyStore)
  1348. {
  1349. hr = myHLastError();
  1350. _JumpError(hr, error, "CertOpenStore");
  1351. }
  1352. NotAfter = pccCA->pCertInfo->NotAfter;
  1353. for (i = cCertOld; i > 0; i--)
  1354. {
  1355. hr = SetCARegOldCertHashByIndex(
  1356. pwszSanitizedName,
  1357. hMyStore,
  1358. pwszDN,
  1359. i - 1,
  1360. &NotAfter);
  1361. _PrintIfError(hr, "SetCARegOldCertHashByIndex");
  1362. }
  1363. }
  1364. hr = S_OK;
  1365. error:
  1366. if (NULL != pwszDN)
  1367. {
  1368. LocalFree(pwszDN);
  1369. }
  1370. if (NULL != hMyStore)
  1371. {
  1372. CertCloseStore(hMyStore, 0);
  1373. }
  1374. return(hr);
  1375. }
  1376. HRESULT
  1377. CreateCertificates(
  1378. IN OUT PER_COMPONENT_DATA *pComp,
  1379. IN HWND hwnd)
  1380. {
  1381. HRESULT hr;
  1382. HCRYPTPROV hCryptProv = NULL;
  1383. HCERTSTORE hStore = NULL;
  1384. CRYPT_KEY_PROV_INFO keyProvInfo;
  1385. WCHAR wszEnrollPath[MAX_PATH];
  1386. CERT_CONTEXT const *pccCA = NULL;
  1387. BYTE *pbEncoded = NULL;
  1388. WCHAR *pwszEnrollPath = NULL;
  1389. WCHAR *pwszDir = NULL;
  1390. WCHAR *pwszFolderPath = NULL;
  1391. DWORD dwSize;
  1392. wszEnrollPath[0] = L'\0';
  1393. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  1394. ZeroMemory(&keyProvInfo, sizeof(keyProvInfo));
  1395. if (NULL == pServer->pwszKeyContainerName && pComp->fUnattended)
  1396. {
  1397. // create a new key if unattended
  1398. hr = csiGenerateCAKeys(
  1399. pServer->pwszSanitizedName,
  1400. pServer->pCSPInfo->pwszProvName,
  1401. pServer->pCSPInfo->dwProvType,
  1402. pServer->pCSPInfo->fMachineKeyset,
  1403. pServer->dwKeyLength,
  1404. pComp->hInstance,
  1405. pComp->fUnattended,
  1406. hwnd,
  1407. &pComp->CA.pServer->fKeyGenFailed);
  1408. if (S_OK != hr)
  1409. {
  1410. CertErrorMessageBox(
  1411. pComp->hInstance,
  1412. pComp->fUnattended,
  1413. hwnd,
  1414. IDS_ERR_FATAL_GENKEY,
  1415. hr,
  1416. pServer->pwszSanitizedName);
  1417. _JumpIfError(hr, error, "csiGenerateCAKeys");
  1418. }
  1419. // now set this as the existing key
  1420. hr = SetKeyContainerName(pServer, pServer->pwszSanitizedName);
  1421. _JumpIfError(hr, error, "SetKeyContainerName");
  1422. }
  1423. hr = csiFillKeyProvInfo(
  1424. pServer->pwszKeyContainerName,
  1425. pServer->pCSPInfo->pwszProvName,
  1426. pServer->pCSPInfo->dwProvType,
  1427. pServer->pCSPInfo->fMachineKeyset,
  1428. &keyProvInfo);
  1429. _JumpIfError(hr, error, "csiFillKeyProvInfo");
  1430. // get csp handle
  1431. if (!myCertSrvCryptAcquireContext(
  1432. &hCryptProv,
  1433. pServer->pwszKeyContainerName,
  1434. pServer->pCSPInfo->pwszProvName,
  1435. pServer->pCSPInfo->dwProvType,
  1436. pComp->fUnattended? CRYPT_SILENT : 0, // query
  1437. pServer->pCSPInfo->fMachineKeyset))
  1438. {
  1439. hr = myHLastError();
  1440. _JumpError(hr, error, "myCertSrvCryptAcquireContext");
  1441. }
  1442. if (hCryptProv == NULL)
  1443. {
  1444. hr = E_HANDLE;
  1445. _JumpError(hr, error, "myCertSrvCryptAcquireContext");
  1446. }
  1447. // open certificate store
  1448. if (NULL == pServer->hMyStore)
  1449. {
  1450. pServer->hMyStore = CertOpenStore(
  1451. CERT_STORE_PROV_SYSTEM_W,
  1452. X509_ASN_ENCODING,
  1453. NULL, // hProv
  1454. CERT_SYSTEM_STORE_LOCAL_MACHINE |
  1455. CERT_STORE_ENUM_ARCHIVED_FLAG,
  1456. wszMY_CERTSTORE);
  1457. if (NULL == pServer->hMyStore)
  1458. {
  1459. // no store exists, done
  1460. hr = myHLastError();
  1461. _JumpIfError(hr, error, "CertOpenStore");
  1462. }
  1463. }
  1464. if (NULL != pServer->pccExistingCert)
  1465. {
  1466. // reuse cert, mark unarchived
  1467. CertSetCertificateContextProperty(
  1468. pServer->pccExistingCert,
  1469. CERT_ARCHIVED_PROP_ID,
  1470. 0,
  1471. NULL);
  1472. }
  1473. if (IsSubordinateCA(pServer->CAType) && NULL == pServer->pccExistingCert)
  1474. {
  1475. hr = BuildCAHierarchy(hCryptProv, pComp, &keyProvInfo, hwnd);
  1476. _JumpIfError(hr, error, "BuildCAHierarchy");
  1477. }
  1478. else
  1479. {
  1480. WCHAR const *pwszCertName;
  1481. DWORD cwc;
  1482. BuildPath(
  1483. wszEnrollPath,
  1484. ARRAYSIZE(wszEnrollPath),
  1485. pComp->pwszSystem32,
  1486. wszCERTENROLLSHAREPATH);
  1487. hr = csiBuildFileName(
  1488. wszEnrollPath,
  1489. pServer->pwszSanitizedName,
  1490. L".crt",
  1491. CANAMEIDTOICERT(pServer->dwCertNameId),
  1492. &pwszEnrollPath,
  1493. pComp->hInstance,
  1494. pComp->fUnattended,
  1495. NULL);
  1496. _JumpIfError(hr, error, "csiBuildFileName");
  1497. CSASSERT(NULL != pServer->pwszCACertFile);
  1498. pwszCertName = wcsrchr(pServer->pwszCACertFile, L'\\');
  1499. CSASSERT(NULL != pwszCertName);
  1500. cwc = SAFE_SUBTRACT_POINTERS(pwszCertName, pServer->pwszCACertFile);
  1501. pwszDir = (WCHAR *) LocalAlloc(LMEM_FIXED, (cwc + 1) * sizeof(WCHAR));
  1502. if (NULL == pwszDir)
  1503. {
  1504. hr = E_OUTOFMEMORY;
  1505. _JumpError(hr, error, "LocalAlloc");
  1506. }
  1507. CopyMemory(pwszDir, pServer->pwszCACertFile, cwc * sizeof(WCHAR));
  1508. pwszDir[cwc] = L'\0';
  1509. hr = csiBuildFileName(
  1510. pwszDir,
  1511. pServer->pwszSanitizedName,
  1512. L".crt",
  1513. CANAMEIDTOICERT(pServer->dwCertNameId),
  1514. &pwszFolderPath,
  1515. pComp->hInstance,
  1516. pComp->fUnattended,
  1517. NULL);
  1518. _JumpIfError(hr, error, "csiBuildFileName");
  1519. // create and save a selfsigned root cert
  1520. hr = csiBuildAndWriteCert(
  1521. hCryptProv,
  1522. pServer,
  1523. pwszFolderPath,
  1524. pwszEnrollPath,
  1525. pServer->pccExistingCert, // if NULL, we will build a new cert
  1526. &pccCA,
  1527. wszCERTTYPE_CA,
  1528. pComp->hInstance,
  1529. pComp->fUnattended,
  1530. hwnd);
  1531. if (S_OK != hr)
  1532. {
  1533. CertErrorMessageBox(
  1534. pComp->hInstance,
  1535. pComp->fUnattended,
  1536. hwnd,
  1537. IDS_ERR_BUILDCERT,
  1538. hr,
  1539. NULL);
  1540. _JumpError(hr, error, "csiBuildAndWriteCert");
  1541. }
  1542. hr = SetCARegOldCertHashes(
  1543. pServer->pwszSanitizedName,
  1544. CANAMEIDTOICERT(pServer->dwCertNameId),
  1545. pccCA);
  1546. _JumpIfError(hr, error, "SetCARegOldCertHashes");
  1547. hr = mySetCARegHash(
  1548. pServer->pwszSanitizedName,
  1549. CSRH_CASIGCERT,
  1550. CANAMEIDTOICERT(pServer->dwCertNameId),
  1551. pccCA);
  1552. _JumpIfError(hr, error, "mySetCARegHash");
  1553. hr = csiSaveCertAndKeys(pccCA, NULL, &keyProvInfo, pServer->CAType);
  1554. _JumpIfError(hr, error, "csiSaveCertAndKeys");
  1555. if (pServer->fUseDS)
  1556. {
  1557. hr = csiSetupCAInDS(
  1558. hwnd,
  1559. pComp->pwszServerName,
  1560. pServer->pwszSanitizedName,
  1561. pServer->pwszCACommonName,
  1562. NULL,
  1563. pServer->CAType,
  1564. CANAMEIDTOICERT(pServer->dwCertNameId),
  1565. CANAMEIDTOIKEY(pServer->dwCertNameId),
  1566. FALSE, // fRenew
  1567. pccCA);
  1568. _PrintIfError(hr, "csiSetupCAInDS");
  1569. if (hr == S_OK)
  1570. pServer->fSavedCAInDS = TRUE;
  1571. }
  1572. }
  1573. hr = S_OK;
  1574. error:
  1575. csiFreeKeyProvInfo(&keyProvInfo);
  1576. if (NULL != pbEncoded)
  1577. {
  1578. LocalFree(pbEncoded);
  1579. }
  1580. if (NULL != pwszDir)
  1581. {
  1582. LocalFree(pwszDir);
  1583. }
  1584. if (NULL != pwszFolderPath)
  1585. {
  1586. LocalFree(pwszFolderPath);
  1587. }
  1588. if (NULL != pwszEnrollPath)
  1589. {
  1590. LocalFree(pwszEnrollPath);
  1591. }
  1592. if (NULL != pccCA)
  1593. {
  1594. CertFreeCertificateContext(pccCA);
  1595. }
  1596. if (NULL != hCryptProv)
  1597. {
  1598. CryptReleaseContext(hCryptProv, 0);
  1599. }
  1600. CSILOG(hr, IDS_LOG_CREATE_CERTIFICATE, NULL, NULL, NULL);
  1601. return(hr);
  1602. }
  1603. HRESULT
  1604. StartCertsrvService(BOOL fSilent)
  1605. {
  1606. HRESULT hr;
  1607. SC_HANDLE hSCManager = NULL;
  1608. SC_HANDLE hSCCertsvc = NULL;
  1609. SERVICE_STATUS status;
  1610. DWORD dwAttempt;
  1611. BOOL fSawPending;
  1612. WCHAR const *apwszSilentArg[1] = {L"-s"};
  1613. hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  1614. if (NULL == hSCManager)
  1615. {
  1616. hr = myHLastError();
  1617. _JumpError(hr, error, "OpenSCManager");
  1618. }
  1619. hSCCertsvc = OpenService(
  1620. hSCManager,
  1621. wszSERVICE_NAME,
  1622. SERVICE_ALL_ACCESS);
  1623. if (NULL == hSCCertsvc)
  1624. {
  1625. hr = myHLastError();
  1626. _JumpErrorStr(hr, error, "OpenService", wszSERVICE_NAME);
  1627. }
  1628. // START the service
  1629. if (!StartService(hSCCertsvc,
  1630. fSilent ? 1 : 0,
  1631. fSilent ? apwszSilentArg : NULL))
  1632. {
  1633. hr = myHLastError();
  1634. _JumpErrorStr(hr, error, "StartService", wszSERVICE_NAME);
  1635. }
  1636. // get out after it is really started
  1637. fSawPending = FALSE;
  1638. for (dwAttempt = 0; dwAttempt < CERT_MAX_ATTEMPT; dwAttempt++)
  1639. {
  1640. DBGCODE(status.dwCurrentState = -1);
  1641. if (!QueryServiceStatus(hSCCertsvc, &status))
  1642. {
  1643. // query failed, ignore error
  1644. hr = S_OK;
  1645. _JumpErrorStr(
  1646. myHLastError(), // Display ignored error
  1647. error,
  1648. "QueryServiceStatus",
  1649. wszSERVICE_NAME);
  1650. }
  1651. if (SERVICE_START_PENDING != status.dwCurrentState &&
  1652. SERVICE_STOPPED != status.dwCurrentState)
  1653. {
  1654. // it was started already
  1655. break;
  1656. }
  1657. DBGPRINT((
  1658. DBG_SS_CERTOCM,
  1659. "Starting %ws service: current state=%d\n",
  1660. wszSERVICE_NAME,
  1661. status.dwCurrentState));
  1662. if (fSawPending && SERVICE_STOPPED == status.dwCurrentState)
  1663. {
  1664. hr = HRESULT_FROM_WIN32(ERROR_SERVICE_NEVER_STARTED);
  1665. _JumpErrorStr(
  1666. hr,
  1667. error,
  1668. "Service won't start",
  1669. wszSERVICE_NAME);
  1670. }
  1671. if (SERVICE_START_PENDING == status.dwCurrentState)
  1672. {
  1673. fSawPending = TRUE;
  1674. }
  1675. Sleep(CERT_HALF_SECOND);
  1676. }
  1677. if (dwAttempt >= CERT_MAX_ATTEMPT)
  1678. {
  1679. DBGPRINT((
  1680. DBG_SS_CERTOCM,
  1681. "Timeout starting %ws service: current state=%d\n",
  1682. wszSERVICE_NAME,
  1683. status.dwCurrentState));
  1684. }
  1685. else
  1686. {
  1687. DBGPRINT((
  1688. DBG_SS_CERTOCM,
  1689. "Started %ws service\n",
  1690. wszSERVICE_NAME));
  1691. }
  1692. hr = S_OK;
  1693. error:
  1694. if (NULL != hSCCertsvc)
  1695. {
  1696. CloseServiceHandle(hSCCertsvc);
  1697. }
  1698. if (NULL != hSCManager)
  1699. {
  1700. CloseServiceHandle(hSCManager);
  1701. }
  1702. CSILOG(hr, IDS_LOG_START_SERVICE, NULL, NULL, NULL);
  1703. return(hr);
  1704. }
  1705. HRESULT
  1706. EnforceCertFileExtensions(
  1707. PER_COMPONENT_DATA *pComp)
  1708. {
  1709. HRESULT hr;
  1710. WCHAR *pwszTmp = NULL;
  1711. WCHAR *pwszSuffix;
  1712. BOOL fAppendExtension = TRUE;
  1713. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  1714. if (NULL == pServer->pwszCACertFile)
  1715. {
  1716. // no ca cert file
  1717. goto done;
  1718. }
  1719. // make enough to hold extra extension crt
  1720. pwszTmp = (WCHAR *) LocalAlloc(
  1721. LMEM_FIXED,
  1722. (wcslen(pServer->pwszCACertFile) + 5) * sizeof(WCHAR));
  1723. _JumpIfOutOfMemory(hr, error, pwszTmp);
  1724. wcscpy(pwszTmp, pServer->pwszCACertFile);
  1725. // check to make sure our self-signed file has the right extension
  1726. // Is there an extension?
  1727. pwszSuffix = wcsrchr(pwszTmp, L'.');
  1728. if (NULL != pwszSuffix)
  1729. {
  1730. // Is the stuff after the '.' already a 'crt' extension?
  1731. if (0 == lstrcmpi(pwszSuffix, L".crt"))
  1732. {
  1733. fAppendExtension = FALSE;
  1734. }
  1735. else if (pwszSuffix[1] == L'\0') // Is '.' last character?
  1736. {
  1737. while (pwszSuffix >= pwszTmp && *pwszSuffix == L'.')
  1738. {
  1739. *pwszSuffix-- = L'\0';
  1740. }
  1741. }
  1742. }
  1743. if (fAppendExtension)
  1744. {
  1745. // Apply the extension
  1746. wcscat(pwszTmp, L".crt");
  1747. // free old one
  1748. LocalFree(pServer->pwszCACertFile);
  1749. pServer->pwszCACertFile = pwszTmp;
  1750. pwszTmp = NULL;
  1751. }
  1752. done:
  1753. hr = S_OK;
  1754. error:
  1755. if (NULL != pwszTmp)
  1756. {
  1757. LocalFree(pwszTmp);
  1758. }
  1759. return(hr);
  1760. }
  1761. HRESULT
  1762. PrepareEDBDirectory(
  1763. HWND hwnd,
  1764. PER_COMPONENT_DATA *pComp,
  1765. WCHAR const *pwszDir)
  1766. {
  1767. HRESULT hr;
  1768. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  1769. DWORD dwAttr = GetFileAttributes(pwszDir);
  1770. if(MAXDWORD==dwAttr)
  1771. {
  1772. // file not found or other error
  1773. hr = myHLastError();
  1774. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  1775. {
  1776. _JumpError(hr, error, "CreateDirectory");
  1777. }
  1778. hr = S_OK;
  1779. if (!CreateDirectory(pwszDir, NULL))
  1780. {
  1781. hr = myHLastError();
  1782. _JumpError(hr, error, "CreateDirectory");
  1783. }
  1784. }
  1785. if(!(dwAttr&FILE_ATTRIBUTE_DIRECTORY))
  1786. {
  1787. // file already exists but it's not a directory
  1788. hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
  1789. _JumpError(hr, error, "CreateDirectory");
  1790. }
  1791. if (!pServer->fPreserveDB)
  1792. {
  1793. hr = myDeleteDBFilesInDir(pwszDir);
  1794. _JumpIfError(hr, error, "myDeleteDBFilesInDir");
  1795. }
  1796. hr = S_OK;
  1797. error:
  1798. if(S_OK != hr)
  1799. {
  1800. CertErrorMessageBox(
  1801. pComp->hInstance,
  1802. pComp->fUnattended,
  1803. hwnd,
  1804. 0,
  1805. hr,
  1806. L""); // only message is the system error message
  1807. }
  1808. return(hr);
  1809. }
  1810. //--------------------------------------------------------------------
  1811. // Create the web configuration files
  1812. HRESULT
  1813. CreateCertWebIncPages(
  1814. IN HWND hwnd,
  1815. IN PER_COMPONENT_DATA *pComp,
  1816. IN BOOL bIsServer,
  1817. IN BOOL fUpgrade)
  1818. {
  1819. HRESULT hr;
  1820. CSASSERT(NULL != pComp);
  1821. // create the web configuration file
  1822. hr = CreateCertWebDatIncPage(pComp, bIsServer);
  1823. _JumpIfError(hr, error, "CreateCertWebDatIncPage");
  1824. error:
  1825. CSILOG(hr, IDS_LOG_WEB_INCLUDE, NULL, NULL, NULL);
  1826. return hr;
  1827. }
  1828. //--------------------------------------------------------------------
  1829. HRESULT
  1830. EnableVRootsAndShares(
  1831. IN BOOL fFileSharesOnly,
  1832. IN BOOL fUpgrade,
  1833. IN BOOL fServer,
  1834. IN PER_COMPONENT_DATA *pComp)
  1835. {
  1836. HRESULT hr;
  1837. DWORD Flags = VFF_CREATEFILESHARES |
  1838. VFF_SETREGFLAGFIRST |
  1839. VFF_SETRUNONCEIFERROR |
  1840. VFF_CLEARREGFLAGIFOK;
  1841. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  1842. CSASSERT(!fServer || NULL != pServer);
  1843. CSASSERT(fServer || NULL != pComp->CA.pClient);
  1844. if (!fFileSharesOnly)
  1845. {
  1846. Flags |= VFF_CREATEVROOTS;
  1847. }
  1848. // if NT GUI mode (base setup) VRoot creation will fail during setup
  1849. // because IIS is not yet operational. Make a mark in the registry
  1850. // to try this on NEXT service startup or via runonce.
  1851. hr = myModifyVirtualRootsAndFileShares(
  1852. Flags,
  1853. fServer? pServer->CAType : pComp->CA.pClient->WebCAType,
  1854. FALSE, // synchronous -- blocking call
  1855. VFCSEC_TIMEOUT,
  1856. NULL,
  1857. NULL);
  1858. _JumpIfError(hr, error, "myModifyVirtualRootsAndFileShares");
  1859. if (!fUpgrade)
  1860. {
  1861. pServer->fCreatedShare = TRUE;
  1862. if (!fFileSharesOnly)
  1863. {
  1864. pComp->fCreatedVRoot = TRUE;
  1865. }
  1866. }
  1867. error:
  1868. return(hr);
  1869. }
  1870. HRESULT
  1871. DisableVRootsAndShares(
  1872. IN BOOL fVRoot,
  1873. IN BOOL fFileShares)
  1874. {
  1875. HRESULT hr;
  1876. DWORD Flags = 0;
  1877. if (fVRoot)
  1878. {
  1879. Flags |= VFF_DELETEVROOTS;
  1880. }
  1881. if (fFileShares)
  1882. {
  1883. Flags |= VFF_DELETEFILESHARES;
  1884. }
  1885. if (0 == Flags)
  1886. {
  1887. goto done;
  1888. }
  1889. hr = myModifyVirtualRootsAndFileShares(
  1890. Flags,
  1891. ENUM_UNKNOWN_CA,
  1892. FALSE, // synchronous -- blocking call
  1893. VFCSEC_TIMEOUT,
  1894. NULL,
  1895. NULL);
  1896. _JumpIfError(hr, error, "myModifyVirtualRootsAndFileShares");
  1897. done:
  1898. hr = S_OK;
  1899. error:
  1900. return(hr);
  1901. }
  1902. HRESULT
  1903. InstallClient(
  1904. HWND hwnd,
  1905. PER_COMPONENT_DATA *pComp)
  1906. {
  1907. BOOL fCoInit = FALSE;
  1908. HRESULT hr;
  1909. hr = CoInitialize(NULL);
  1910. if (S_OK != hr && S_FALSE != hr)
  1911. {
  1912. _JumpError(hr, error, "CoInitialize");
  1913. }
  1914. fCoInit = TRUE;
  1915. certocmBumpGasGauge(pComp, 10 DBGPARM(L"InstallClient"));
  1916. hr = CreateWebClientRegEntries(FALSE, pComp);
  1917. _JumpIfError(hr, error, "CreateWebClientRegEntries");
  1918. certocmBumpGasGauge(pComp, 30 DBGPARM(L"InstallClient"));
  1919. hr = RegisterAndUnRegisterDLLs(RD_CLIENT, pComp, hwnd);
  1920. _JumpIfError(hr, error, "RegisterAndUnRegisterDLLs");
  1921. certocmBumpGasGauge(pComp, 50 DBGPARM(L"InstallClient"));
  1922. DeleteProgramGroups(FALSE, pComp);
  1923. hr = CreateProgramGroups(TRUE, pComp, hwnd);
  1924. _JumpIfError(hr, error, "CreateProgramGroups");
  1925. certocmBumpGasGauge(pComp, 70 DBGPARM(L"InstallClient"));
  1926. hr = CreateCertWebIncPages(hwnd, pComp, FALSE /*IsServer*/, FALSE);
  1927. _JumpIfError(hr, error, "CreateCertWebIncPages");
  1928. hr = RenameMiscTargets(hwnd, pComp, FALSE);
  1929. _JumpIfError(hr, error, "RenameMiscTargets");
  1930. certocmBumpGasGauge(pComp, 80 DBGPARM(L"InstallClient"));
  1931. hr = EnableVRootsAndShares(FALSE, FALSE, FALSE, pComp);
  1932. _JumpIfError(hr, error, "EnableVRootsAndShares");
  1933. certocmBumpGasGauge(pComp, 100 DBGPARM(L"InstallClient"));
  1934. error:
  1935. if (fCoInit)
  1936. {
  1937. CoUninitialize();
  1938. }
  1939. CSILOG(hr, IDS_LOG_INSTALL_CLIENT, NULL, NULL, NULL);
  1940. return(hr);
  1941. }
  1942. HRESULT
  1943. RemoveWebClientRegEntries(VOID)
  1944. {
  1945. HRESULT hr;
  1946. hr = myDeleteCertRegValue(NULL, NULL, NULL, wszREGWEBCLIENTCAMACHINE);
  1947. _PrintIfError(hr, "myDeleteCertRegValue");
  1948. hr = myDeleteCertRegValue(NULL, NULL, NULL, wszREGWEBCLIENTCANAME);
  1949. _PrintIfError(hr, "myDeleteCertRegValue");
  1950. hr = myDeleteCertRegValue(NULL, NULL, NULL, wszREGWEBCLIENTCATYPE);
  1951. _PrintIfError(hr, "myDeleteCertRegValue");
  1952. hr = S_OK;
  1953. //error:
  1954. return hr;
  1955. }
  1956. HRESULT
  1957. InstallServer(
  1958. HWND hwnd,
  1959. PER_COMPONENT_DATA *pComp)
  1960. {
  1961. BOOL fCoInit = FALSE;
  1962. WCHAR *pwszDBFile = NULL;
  1963. DWORD dwSetupStatus;
  1964. HRESULT hr = pComp->hrContinue;
  1965. int ret;
  1966. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  1967. WCHAR *pwszConfig = NULL;
  1968. BOOL fSetDSSecurity;
  1969. _JumpIfError(hr, error, "can't continue");
  1970. hr = UpdateDomainAndUserName(hwnd, pComp);
  1971. _JumpIfError(hr, error, "UpdateDomainAndUserName");
  1972. hr = CoInitialize(NULL);
  1973. if (S_OK != hr && S_FALSE != hr)
  1974. {
  1975. _JumpError(hr, error, "CoInitialize");
  1976. }
  1977. fCoInit = TRUE;
  1978. hr = EnforceCertFileExtensions(pComp);
  1979. _JumpIfError(hr, error, "EnforceCertFileExtensions");
  1980. hr = PrepareEDBDirectory(hwnd, pComp, pServer->pwszDBDirectory);
  1981. _JumpIfError(hr, error, "PrepareEDBDirectory");
  1982. hr = PrepareEDBDirectory(hwnd, pComp, pServer->pwszLogDirectory);
  1983. _JumpIfError(hr, error, "PrepareEDBDirectory");
  1984. certocmBumpGasGauge(pComp, 10 DBGPARM(L"InstallServer"));
  1985. // alway uninstall before install
  1986. PreUninstallCore(hwnd, pComp, FALSE);
  1987. UninstallCore(hwnd, pComp, 10, 30, FALSE, FALSE, FALSE);
  1988. hr = CreateServerRegEntries(hwnd, FALSE, pComp);
  1989. _JumpIfError(hr, error, "CreateServerRegEntries");
  1990. if ((IS_SERVER_INSTALL & pComp->dwInstallStatus) &&
  1991. (IS_CLIENT_UPGRADE & pComp->dwInstallStatus))
  1992. {
  1993. // case of install server only and keep web client
  1994. // remove parent ca config info of the old web client
  1995. hr = RemoveWebClientRegEntries();
  1996. _PrintIfError(hr, "RemoveWebClientRegEntries");
  1997. }
  1998. certocmBumpGasGauge(pComp, 35 DBGPARM(L"InstallServer"));
  1999. hr = RegisterAndUnRegisterDLLs(RD_SERVER, pComp, hwnd);
  2000. _JumpIfError(hr, error, "RegisterAndUnRegisterDLLs");
  2001. certocmBumpGasGauge(pComp, 40 DBGPARM(L"InstallServer"));
  2002. hr = CreateCertificateService(pComp, hwnd);
  2003. _JumpIfError(hr, error, "CreateCertificateService");
  2004. certocmBumpGasGauge(pComp, 45 DBGPARM(L"InstallServer"));
  2005. hr = CreateCertificates(pComp, hwnd);
  2006. _JumpIfError(hr, error, "CreateCertificates");
  2007. certocmBumpGasGauge(pComp, 50 DBGPARM(L"InstallServer"));
  2008. hr = CreateProgramGroups(FALSE, pComp, hwnd);
  2009. _JumpIfError(hr, error, "CreateProgramGroups");
  2010. certocmBumpGasGauge(pComp, 60 DBGPARM(L"InstallServer"));
  2011. hr = CreateCertWebIncPages(hwnd, pComp, TRUE /*IsServer*/, FALSE);
  2012. _JumpIfError(hr, error, "CreateCertWebIncPages");
  2013. hr = RenameMiscTargets(hwnd, pComp, TRUE);
  2014. _JumpIfError(hr, error, "RenameMiscTargets");
  2015. certocmBumpGasGauge(pComp, 70 DBGPARM(L"InstallServer"));
  2016. hr = RegisterDcomServer(
  2017. CLSID_CCertRequestD,
  2018. wszREQUESTFRIENDLYNAME,
  2019. wszREQUESTVERINDPROGID,
  2020. wszREQUESTPROGID);
  2021. _JumpIfError(hr, error, "RegisterDcomServer");
  2022. hr = RegisterDcomServer(
  2023. CLSID_CCertAdminD,
  2024. wszADMINFRIENDLYNAME,
  2025. wszADMINVERINDPROGID,
  2026. wszADMINPROGID);
  2027. _JumpIfError(hr, error, "RegisterDcomServer");
  2028. certocmBumpGasGauge(pComp, 80 DBGPARM(L"InstallServer"));
  2029. hr = RegisterDcomApp(CLSID_CCertRequestD);
  2030. _JumpIfError(hr, error, "RegisterDcomApp");
  2031. certocmBumpGasGauge(pComp, 90 DBGPARM(L"InstallServer"));
  2032. if (pServer->fUseDS)
  2033. {
  2034. hr = AddCAMachineToCertPublishers();
  2035. _JumpIfError(hr, error, "AddCAMachineToCertPublishers");
  2036. hr = InitializeCertificateTemplates();
  2037. _JumpIfError(hr, error, "InitializeCertificateTemplates");
  2038. }
  2039. certocmBumpGasGauge(pComp, 95 DBGPARM(L"InstallServer"));
  2040. // Set the security locally.
  2041. // A SubCA sets security when it receives its certificate from
  2042. // its parent. ALL OTHER CA installs (Root & reuse of existing certs)
  2043. // need to have security set now.
  2044. // On a SubCA the DS object security will have been set
  2045. // by a previous call in initlib if we already got our cert, or it will
  2046. // be set later when we install our cert.
  2047. // However, root certs install doesn't run completefrompkcs7(), so
  2048. // ds security on ent roots is never set. We must set it here.
  2049. // TODO: set security properly at DS object creation time!
  2050. fSetDSSecurity = (IsRootCA(pServer->CAType) || pServer->pccExistingCert);
  2051. hr = csiInitializeCertSrvSecurity(
  2052. pServer->pwszSanitizedName,
  2053. pServer->fUseDS,
  2054. fSetDSSecurity? pServer->fUseDS : FALSE); // clean SUBCA: happens during cert install, ROOT & reuse cert: apply now
  2055. _JumpIfError(hr, error, "csiInitializeCertSrvSecurity");
  2056. hr = GetSetupStatus(pServer->pwszSanitizedName, &dwSetupStatus);
  2057. if (S_OK == hr)
  2058. {
  2059. if (IsSubordinateCA(pServer->CAType) &&
  2060. (SETUP_SUSPEND_FLAG & dwSetupStatus) &&
  2061. (SETUP_REQUEST_FLAG & dwSetupStatus))
  2062. {
  2063. // put out an info dlg
  2064. CertInfoMessageBox(
  2065. pComp->hInstance,
  2066. pComp->fUnattended,
  2067. hwnd,
  2068. IDS_INCOMPLETE_REQUEST,
  2069. pServer->pwszRequestFile);
  2070. }
  2071. }
  2072. else
  2073. {
  2074. _PrintError(hr, "GetSetupStatus");
  2075. }
  2076. certocmBumpGasGauge(pComp, 100 DBGPARM(L"InstallServer"));
  2077. hr = S_OK;
  2078. error:
  2079. if (NULL != pwszConfig)
  2080. {
  2081. LocalFree(pwszConfig);
  2082. }
  2083. if (NULL != pwszDBFile)
  2084. {
  2085. LocalFree(pwszDBFile);
  2086. }
  2087. if (fCoInit)
  2088. {
  2089. CoUninitialize();
  2090. }
  2091. CSILOG(hr, IDS_LOG_INSTALL_SERVER, NULL, NULL, NULL);
  2092. return(hr);
  2093. }
  2094. HRESULT
  2095. CreateCertsrvDirectories(
  2096. IN PER_COMPONENT_DATA *pComp,
  2097. IN BOOL fUpgrade,
  2098. IN BOOL fServer)
  2099. {
  2100. HRESULT hr;
  2101. WCHAR wszCertEnroll[MAX_PATH];
  2102. wszCertEnroll[0] = L'\0';
  2103. BuildPath(
  2104. wszCertEnroll,
  2105. ARRAYSIZE(wszCertEnroll),
  2106. pComp->pwszSystem32,
  2107. wszCERTENROLLSHAREPATH);
  2108. if (0 == CreateDirectory(wszCertEnroll, NULL))
  2109. {
  2110. hr = myHLastError();
  2111. if (HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) != hr)
  2112. {
  2113. _JumpErrorStr(hr, error, "CreateDirectory", wszCertEnroll);
  2114. }
  2115. }
  2116. if (fServer && NULL != pComp->CA.pServer->pwszSharedFolder)
  2117. {
  2118. if (pComp->fUnattended && !fUpgrade)
  2119. {
  2120. // make sure shared folder is created
  2121. if (!CreateDirectory(pComp->CA.pServer->pwszSharedFolder, NULL))
  2122. {
  2123. hr = myHLastError();
  2124. if (HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) != hr)
  2125. {
  2126. _JumpErrorStr(hr, error, "CreateDirectory",
  2127. pComp->CA.pServer->pwszSharedFolder);
  2128. }
  2129. }
  2130. }
  2131. if (!fUpgrade)
  2132. {
  2133. // set security on shared folder to
  2134. // FULL: Admins, LocalSystem, DomainAdmins
  2135. // READ: Everyone
  2136. // NOTE: in upgrade path, the system doesn't enable file share yet
  2137. // so skip the call
  2138. hr = csiSetAdminOnlyFolderSecurity(
  2139. pComp->CA.pServer->pwszSharedFolder,
  2140. TRUE, // apply Everyone:READ
  2141. pComp->CA.pServer->fUseDS);
  2142. _JumpIfError(hr, error, "csiSetAdminOnlyFolderSecurity");
  2143. }
  2144. }
  2145. hr = S_OK;
  2146. error:
  2147. return hr;
  2148. }
  2149. // following remove unused file/directory/registry
  2150. #define wszOLDHELP L"..\\help\\"
  2151. #define wszOLDCERTADM L"\\certadm"
  2152. #define wszOLDCERTQUE L"\\certque"
  2153. VOID
  2154. DeleteOldFilesAndDirectories(
  2155. IN PER_COMPONENT_DATA *pComp)
  2156. {
  2157. HRESULT hr;
  2158. WCHAR wszPath[MAX_PATH];
  2159. WCHAR *pwszCertsrv;
  2160. wszPath[0] = L'\0';
  2161. // old help dir path
  2162. wcscpy(wszPath, pComp->pwszSystem32);
  2163. wcscat(wszPath, wszOLDHELP);
  2164. wcscat(wszPath, wszCERTSRV);
  2165. // remove old help files
  2166. hr = myRemoveFilesAndDirectory(wszPath, TRUE);
  2167. _PrintIfErrorStr(hr, "myRemoveFilesAndDirectory", wszPath);
  2168. // point to system32\certsrv
  2169. wcscpy(wszPath, pComp->pwszSystem32);
  2170. wcscat(wszPath, wszCERTSRV);
  2171. pwszCertsrv = &wszPath[wcslen(wszPath)];
  2172. // old vroot dir path
  2173. wcscpy(pwszCertsrv, wszOLDCERTADM);
  2174. hr = myRemoveFilesAndDirectory(wszPath, TRUE);
  2175. _PrintIfErrorStr(hr, "myRemoveFilesAndDirectory", wszPath);
  2176. wcscpy(pwszCertsrv, wszOLDCERTQUE);
  2177. hr = myRemoveFilesAndDirectory(wszPath, TRUE);
  2178. _PrintIfErrorStr(hr, "myRemoveFilesAndDirectory", wszPath);
  2179. // delete some obsolete registry keys and values
  2180. // old doc sub-component
  2181. hr = myDeleteCertRegValueEx(wszREGKEYOCMSUBCOMPONENTS,
  2182. NULL,
  2183. NULL,
  2184. wszOLDDOCCOMPONENT,
  2185. TRUE); //absolute path,
  2186. _PrintIfErrorStr2(hr, "myDeleteCertRegValueEx", wszOLDDOCCOMPONENT, hr);
  2187. // old CA cert serial number
  2188. if (NULL != pComp->CA.pServer &&
  2189. NULL != pComp->CA.pServer->pwszSanitizedName)
  2190. {
  2191. hr = myDeleteCertRegValue(
  2192. pComp->CA.pServer->pwszSanitizedName,
  2193. NULL,
  2194. NULL,
  2195. wszREGCASERIALNUMBER);
  2196. _PrintIfErrorStr2(hr, "myDeleteCertRegValue", wszREGCASERIALNUMBER, hr);
  2197. }
  2198. }
  2199. VOID
  2200. DeleteObsoleteResidue()
  2201. {
  2202. HRESULT hr;
  2203. hr = myDeleteCertRegValueEx(wszREGKEYKEYSNOTTORESTORE,
  2204. NULL,
  2205. NULL,
  2206. wszREGRESTORECERTIFICATEAUTHORITY,
  2207. TRUE); //absolute path,
  2208. _PrintIfErrorStr(hr, "myDeleteCertRegValueEx",
  2209. wszREGRESTORECERTIFICATEAUTHORITY);
  2210. hr = myDeleteCertRegValueEx(wszREGKEYFILESNOTTOBACKUP,
  2211. NULL,
  2212. NULL,
  2213. wszREGRESTORECERTIFICATEAUTHORITY,
  2214. TRUE); //absolute path,
  2215. _PrintIfErrorStr(hr, "myDeleteCertRegValueEx",
  2216. wszREGRESTORECERTIFICATEAUTHORITY);
  2217. }
  2218. HRESULT
  2219. InstallCore(
  2220. IN HWND hwnd,
  2221. IN PER_COMPONENT_DATA *pComp,
  2222. IN BOOL fServer)
  2223. {
  2224. HRESULT hr = pComp->hrContinue;
  2225. _JumpIfError(hr, error, "can't continue");
  2226. hr = CreateCertsrvDirectories(pComp, FALSE, fServer);
  2227. _JumpIfError(hr, error, "CreateCertsrvDirectories");
  2228. // Trigger an autoenroll to download root certs (see bug# 341568)
  2229. if(IsEnterpriseCA(pComp->CA.pServer->CAType))
  2230. {
  2231. hr = TriggerAutoenrollment();
  2232. _JumpIfError(hr, error, "TriggerAutoenrollment");
  2233. }
  2234. if (fServer)
  2235. {
  2236. hr = InstallServer(hwnd, pComp);
  2237. _JumpIfError(hr, error, "InstallServer");
  2238. }
  2239. else
  2240. {
  2241. hr = InstallClient(hwnd, pComp);
  2242. _JumpIfError(hr, error, "InstallClient");
  2243. }
  2244. if (g_fW3SvcRunning)
  2245. {
  2246. hr = StartAndStopService(pComp->hInstance,
  2247. pComp->fUnattended,
  2248. hwnd,
  2249. wszW3SVCNAME,
  2250. FALSE,
  2251. FALSE,
  2252. 0, //doesn't matter since no confirm
  2253. &g_fW3SvcRunning);
  2254. _PrintIfError(hr, "StartAndStopService");
  2255. }
  2256. DeleteOldFilesAndDirectories(pComp);
  2257. hr = S_OK;
  2258. error:
  2259. return(hr);
  2260. }
  2261. HRESULT
  2262. BuildMultiStringList(
  2263. IN WCHAR const * const *apwsz,
  2264. IN DWORD cpwsz,
  2265. OUT WCHAR **ppwszz)
  2266. {
  2267. HRESULT hr;
  2268. DWORD i;
  2269. DWORD cwc;
  2270. WCHAR *pwc;
  2271. WCHAR *apwszEmpty[] = { L"", };
  2272. if (0 == cpwsz)
  2273. {
  2274. cpwsz = ARRAYSIZE(apwszEmpty);
  2275. apwsz = apwszEmpty;
  2276. }
  2277. cwc = 1;
  2278. for (i = 0; i < cpwsz; i++)
  2279. {
  2280. cwc += wcslen(apwsz[i]) + 1;
  2281. }
  2282. *ppwszz = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
  2283. _JumpIfOutOfMemory(hr, error, *ppwszz);
  2284. pwc = *ppwszz;
  2285. for (i = 0; i < cpwsz; i++)
  2286. {
  2287. wcscpy(pwc, apwsz[i]);
  2288. pwc += wcslen(pwc) + 1;
  2289. }
  2290. *pwc = L'\0';
  2291. CSASSERT(SAFE_SUBTRACT_POINTERS(pwc, *ppwszz) + 1 == cwc);
  2292. hr = S_OK;
  2293. error:
  2294. return(hr);
  2295. }
  2296. HRESULT
  2297. helperGetDisableExtensionList(
  2298. PER_COMPONENT_DATA *pComp,
  2299. OUT WCHAR **ppwszz)
  2300. {
  2301. HRESULT hr;
  2302. WCHAR *apwszExt[] = {
  2303. L"", // C compiler won't allow empty list
  2304. //TEXT(szOID_ENROLL_CERTTYPE_EXTENSION), // 1.3.6.1.4.1.311.20.2
  2305. };
  2306. hr = BuildMultiStringList(apwszExt, ARRAYSIZE(apwszExt), ppwszz);
  2307. _JumpIfError(hr, error, "BuildMultiStringList");
  2308. error:
  2309. return(hr);
  2310. }
  2311. HRESULT
  2312. helperGetRequestExtensionList(
  2313. PER_COMPONENT_DATA *pComp,
  2314. OUT WCHAR **ppwszz)
  2315. {
  2316. HRESULT hr;
  2317. WCHAR *apwszExt[] = {
  2318. TEXT(szOID_RSA_SMIMECapabilities), // 1.2.840.113549.1.9.15
  2319. TEXT(szOID_CROSS_CERT_DIST_POINTS), // 1.3.6.1.4.1.311.10.9.1
  2320. TEXT(szOID_ENROLL_CERTTYPE_EXTENSION), // 1.3.6.1.4.1.311.20.2
  2321. TEXT(szOID_CERTSRV_CA_VERSION), // 1.3.6.1.4.1.311.21.1
  2322. TEXT(szOID_CERTSRV_PREVIOUS_CERT_HASH), // 1.3.6.1.4.1.311.21.2
  2323. TEXT(szOID_CERTIFICATE_TEMPLATE), // 1.3.6.1.4.1.311.21.7
  2324. TEXT(szOID_APPLICATION_CERT_POLICIES), // 1.3.6.1.4.1.311.21.10
  2325. TEXT(szOID_APPLICATION_POLICY_MAPPINGS), // 1.3.6.1.4.1.311.21.11
  2326. TEXT(szOID_APPLICATION_POLICY_CONSTRAINTS), // 1.3.6.1.4.1.311.21.12
  2327. TEXT(szOID_KEY_USAGE), // 2.5.29.15
  2328. TEXT(szOID_SUBJECT_ALT_NAME2), // 2.5.29.17
  2329. TEXT(szOID_NAME_CONSTRAINTS), // 2.5.29.30
  2330. TEXT(szOID_CERT_POLICIES), // 2.5.29.32
  2331. TEXT(szOID_POLICY_MAPPINGS), // 2.5.29.33
  2332. TEXT(szOID_POLICY_CONSTRAINTS), // 2.5.29.36
  2333. TEXT(szOID_ENHANCED_KEY_USAGE), // 2.5.29.37
  2334. };
  2335. hr = BuildMultiStringList(apwszExt, ARRAYSIZE(apwszExt), ppwszz);
  2336. _JumpIfError(hr, error, "BuildMultiStringList");
  2337. error:
  2338. return(hr);
  2339. }
  2340. HRESULT
  2341. FindCACertByCommonNameAndSerialNumber(
  2342. IN HCERTSTORE hCAStore,
  2343. IN WCHAR const *pwszCommonName,
  2344. IN BYTE const *pbSerialNumber,
  2345. IN DWORD cbSerialNumber,
  2346. CERT_CONTEXT const **ppCACert)
  2347. {
  2348. HRESULT hr;
  2349. CERT_RDN_ATTR rdnAttr = { szOID_COMMON_NAME, CERT_RDN_ANY_TYPE,};
  2350. CERT_RDN rdn = { 1, &rdnAttr };
  2351. CRYPT_INTEGER_BLOB SerialNumber;
  2352. CERT_CONTEXT const *pCACert = NULL;
  2353. CSASSERT(NULL != hCAStore &&
  2354. NULL != pwszCommonName &&
  2355. NULL != pbSerialNumber &&
  2356. NULL != ppCACert);
  2357. *ppCACert = NULL;
  2358. rdnAttr.Value.pbData = (BYTE *) pwszCommonName;
  2359. rdnAttr.Value.cbData = 0;
  2360. pCACert = NULL;
  2361. SerialNumber.pbData = const_cast<BYTE *>(pbSerialNumber);
  2362. SerialNumber.cbData = cbSerialNumber;
  2363. while (TRUE)
  2364. {
  2365. pCACert = CertFindCertificateInStore(
  2366. hCAStore,
  2367. X509_ASN_ENCODING,
  2368. CERT_UNICODE_IS_RDN_ATTRS_FLAG |
  2369. CERT_CASE_INSENSITIVE_IS_RDN_ATTRS_FLAG,
  2370. CERT_FIND_SUBJECT_ATTR,
  2371. &rdn,
  2372. pCACert);
  2373. if (NULL == pCACert)
  2374. {
  2375. hr = myHLastError();
  2376. _JumpError(hr, error, "CertFindCertificateInStore");
  2377. }
  2378. if (myAreSerialNumberBlobsSame(
  2379. &SerialNumber,
  2380. &pCACert->pCertInfo->SerialNumber))
  2381. {
  2382. break; // found correct one
  2383. }
  2384. }
  2385. *ppCACert = pCACert;
  2386. pCACert = NULL;
  2387. hr = S_OK;
  2388. error:
  2389. if (NULL != pCACert)
  2390. {
  2391. CertFreeCertificateContext(pCACert);
  2392. }
  2393. return hr;
  2394. }
  2395. HRESULT
  2396. GetCARegSerialNumber(
  2397. IN WCHAR const *pwszSanitizedCAName,
  2398. OUT BYTE **ppbSerialNumber,
  2399. OUT DWORD *pcbSerialNumber)
  2400. {
  2401. HRESULT hr;
  2402. WCHAR *pwszSerialNumber = NULL;
  2403. BYTE *pbSN = NULL;
  2404. DWORD cbSN;
  2405. hr = myGetCertRegStrValue(
  2406. pwszSanitizedCAName,
  2407. NULL,
  2408. NULL,
  2409. wszREGCASERIALNUMBER,
  2410. &pwszSerialNumber);
  2411. _JumpIfErrorStr2(
  2412. hr,
  2413. error,
  2414. "myGetCertRegStrValue",
  2415. wszREGCASERIALNUMBER,
  2416. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  2417. hr = WszToMultiByteInteger(FALSE, pwszSerialNumber, &cbSN, &pbSN);
  2418. _JumpIfError(hr, error, "WszToMultiByteInteger");
  2419. *ppbSerialNumber = pbSN;
  2420. pbSN = NULL;
  2421. *pcbSerialNumber = cbSN;
  2422. error:
  2423. if (NULL != pwszSerialNumber)
  2424. {
  2425. LocalFree(pwszSerialNumber);
  2426. }
  2427. if (NULL != pbSN)
  2428. {
  2429. LocalFree(pbSN);
  2430. }
  2431. CSASSERT(S_OK == hr || FAILED(hr));
  2432. return(hr);
  2433. }
  2434. HRESULT
  2435. LoadCurrentCACert(
  2436. IN WCHAR const *pwszCommonName,
  2437. IN WCHAR const *pwszSanitizedName,
  2438. IN BOOL fSignTest,
  2439. OUT CERT_CONTEXT const **ppcc,
  2440. OUT DWORD *pdwNameId)
  2441. {
  2442. HRESULT hr;
  2443. DWORD Count;
  2444. HCERTSTORE hMyStore = NULL;
  2445. BYTE *pbSerialNumber = NULL;
  2446. DWORD cbSerialNumber;
  2447. CRYPT_KEY_PROV_INFO *pKey = NULL;
  2448. DWORD cbKey;
  2449. DWORD dwType;
  2450. CERT_CONTEXT const *pcc = NULL;
  2451. WCHAR *pwszProvName = NULL;
  2452. DWORD dwProvType;
  2453. ALG_ID idAlg;
  2454. BOOL fMachineKeyset;
  2455. *ppcc = NULL;
  2456. // get prov name
  2457. hr = myGetCertSrvCSP(
  2458. FALSE, // fEncryptionCSP
  2459. pwszSanitizedName,
  2460. &dwProvType,
  2461. &pwszProvName,
  2462. &idAlg,
  2463. &fMachineKeyset,
  2464. NULL); // pdwKeySize
  2465. _JumpIfError(hr, error, "myGetCertSrvCSP");
  2466. // open my store
  2467. hMyStore = CertOpenStore(
  2468. CERT_STORE_PROV_SYSTEM_W,
  2469. X509_ASN_ENCODING,
  2470. NULL, // hProv
  2471. CERT_SYSTEM_STORE_LOCAL_MACHINE |
  2472. CERT_STORE_ENUM_ARCHIVED_FLAG,
  2473. wszMY_CERTSTORE);
  2474. if (NULL == hMyStore)
  2475. {
  2476. hr = myHLastError();
  2477. _JumpError(hr, error, "CertOpenStore");
  2478. }
  2479. hr = myGetCARegHashCount(pwszSanitizedName, CSRH_CASIGCERT, &Count);
  2480. _JumpIfError(hr, error, "myGetCARegHashCount");
  2481. if (0 == Count)
  2482. {
  2483. *pdwNameId = 0; // renewal wasn't implemented yet
  2484. // find current CA cert by serial number -- the old fashioned way
  2485. hr = GetCARegSerialNumber(
  2486. pwszSanitizedName,
  2487. &pbSerialNumber,
  2488. &cbSerialNumber);
  2489. _JumpIfError(hr, error, "GetCARegSerialNumber");
  2490. hr = FindCACertByCommonNameAndSerialNumber(
  2491. hMyStore,
  2492. pwszCommonName,
  2493. pbSerialNumber,
  2494. cbSerialNumber,
  2495. &pcc);
  2496. _JumpIfError(hr, error, "FindCACertByCommonNameAndSerialNumber");
  2497. }
  2498. else
  2499. {
  2500. hr = myFindCACertByHashIndex(
  2501. hMyStore,
  2502. pwszSanitizedName,
  2503. CSRH_CASIGCERT,
  2504. Count - 1,
  2505. pdwNameId,
  2506. &pcc);
  2507. _JumpIfError(hr, error, "myFindCACertByHashIndex");
  2508. }
  2509. // get the private key provider info
  2510. if (!myCertGetCertificateContextProperty(
  2511. pcc,
  2512. CERT_KEY_PROV_INFO_PROP_ID,
  2513. CERTLIB_USE_LOCALALLOC,
  2514. (VOID **) &pKey,
  2515. &cbKey))
  2516. {
  2517. hr = myHLastError();
  2518. _JumpError(hr, error, "CertGetCertificateContextProperty");
  2519. }
  2520. if (fSignTest)
  2521. {
  2522. // signing testing
  2523. hr = myValidateHashForSigning(
  2524. pKey->pwszContainerName,
  2525. pwszProvName,
  2526. dwProvType,
  2527. fMachineKeyset,
  2528. &pcc->pCertInfo->SubjectPublicKeyInfo,
  2529. idAlg);
  2530. _JumpIfError(hr, error, "myValidateHashForSigning");
  2531. }
  2532. *ppcc = pcc;
  2533. pcc = NULL;
  2534. hr = S_OK;
  2535. error:
  2536. if (NULL != hMyStore)
  2537. {
  2538. CertCloseStore(hMyStore, CERT_CLOSE_STORE_CHECK_FLAG);
  2539. }
  2540. if (NULL != pbSerialNumber)
  2541. {
  2542. LocalFree(pbSerialNumber);
  2543. }
  2544. if (NULL != pKey)
  2545. {
  2546. LocalFree(pKey);
  2547. }
  2548. if (NULL != pwszProvName)
  2549. {
  2550. LocalFree(pwszProvName);
  2551. }
  2552. if (NULL != pcc)
  2553. {
  2554. CertFreeCertificateContext(pcc);
  2555. }
  2556. CSASSERT(S_OK == hr || FAILED(hr));
  2557. return(hr);
  2558. }
  2559. HRESULT
  2560. ArchiveCACertificate(
  2561. IN WCHAR const *pwszSanitizedName)
  2562. {
  2563. HRESULT hr;
  2564. HCERTSTORE hMyStore = NULL;
  2565. DWORD Count;
  2566. DWORD i;
  2567. CERT_CONTEXT const *pCert = NULL;
  2568. DWORD dwNameId;
  2569. CRYPT_DATA_BLOB Archived;
  2570. // open my store
  2571. hMyStore = CertOpenStore(
  2572. CERT_STORE_PROV_SYSTEM_W,
  2573. X509_ASN_ENCODING,
  2574. NULL, // hProv
  2575. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  2576. wszMY_CERTSTORE);
  2577. if (NULL == hMyStore)
  2578. {
  2579. hr = myHLastError();
  2580. _JumpError(hr, error, "CertOpenStore");
  2581. }
  2582. hr = myGetCARegHashCount(pwszSanitizedName, CSRH_CASIGCERT, &Count);
  2583. _JumpIfError(hr, error, "myGetCARegHashCount");
  2584. for (i = 0; i < Count; i++)
  2585. {
  2586. hr = myFindCACertByHashIndex(
  2587. hMyStore,
  2588. pwszSanitizedName,
  2589. CSRH_CASIGCERT,
  2590. i,
  2591. &dwNameId,
  2592. &pCert);
  2593. _PrintIfError(hr, "myFindCACertByHashIndex");
  2594. if (S_OK == hr)
  2595. {
  2596. Archived.cbData = 0;
  2597. Archived.pbData = NULL;
  2598. // We force an archive on the old cert and close it.
  2599. CertSetCertificateContextProperty(
  2600. pCert,
  2601. CERT_ARCHIVED_PROP_ID,
  2602. 0,
  2603. &Archived);
  2604. CertFreeCertificateContext(pCert);
  2605. pCert = NULL;
  2606. }
  2607. }
  2608. hr = S_OK;
  2609. error:
  2610. if (NULL != pCert)
  2611. {
  2612. CertFreeCertificateContext(pCert);
  2613. }
  2614. if (NULL != hMyStore)
  2615. {
  2616. CertCloseStore(hMyStore, CERT_CLOSE_STORE_CHECK_FLAG);
  2617. }
  2618. CSASSERT(S_OK == hr || FAILED(hr));
  2619. return(hr);
  2620. }
  2621. // determine CA info, from build to build upgrade
  2622. HRESULT
  2623. DetermineCAInfoAndType(
  2624. PER_COMPONENT_DATA *pComp)
  2625. {
  2626. HRESULT hr;
  2627. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  2628. ENUM_CATYPES CATypeDummy;
  2629. WCHAR *pwszCommonName = NULL;
  2630. CERT_CONTEXT const *pCACert = NULL;
  2631. DWORD dwNameId;
  2632. // ca type
  2633. hr = myGetCertRegDWValue(
  2634. pServer->pwszSanitizedName,
  2635. NULL,
  2636. NULL,
  2637. wszREGCATYPE,
  2638. (DWORD *) &CATypeDummy);
  2639. if (S_OK == hr)
  2640. {
  2641. pServer->CAType = CATypeDummy;
  2642. }
  2643. else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  2644. {
  2645. _JumpErrorStr(hr, error, "myGetCertRegDWValue", wszREGCATYPE);
  2646. }
  2647. // else keep default CAType flag
  2648. // get current ca common name
  2649. hr = myGetCertRegStrValue(
  2650. pServer->pwszSanitizedName,
  2651. NULL,
  2652. NULL,
  2653. wszREGCOMMONNAME,
  2654. &pwszCommonName);
  2655. _JumpIfErrorStr(hr, error, "myGetCertRegStrValue", wszREGCOMMONNAME);
  2656. hr = LoadCurrentCACert(
  2657. pwszCommonName,
  2658. pServer->pwszSanitizedName,
  2659. FALSE, // don't do signing test during upgrade
  2660. &pCACert,
  2661. &pServer->dwCertNameId);
  2662. _JumpIfError(hr, error, "LoadCurrentCACert");
  2663. // now ready to load DN info
  2664. hr = DetermineExistingCAIdInfo(pServer, pCACert);
  2665. _JumpIfError(hr, error, "DetermineExistingCAIdInfo");
  2666. if (NULL != pServer->pccUpgradeCert)
  2667. {
  2668. CertFreeCertificateContext(pServer->pccUpgradeCert);
  2669. }
  2670. pServer->pccUpgradeCert = pCACert;
  2671. pCACert = NULL;
  2672. error:
  2673. if (NULL != pwszCommonName)
  2674. {
  2675. LocalFree(pwszCommonName);
  2676. }
  2677. if (NULL != pCACert)
  2678. {
  2679. CertFreeCertificateContext(pCACert);
  2680. }
  2681. return(hr);
  2682. }
  2683. // the following will determine ca sanitized name and upgrade path
  2684. HRESULT
  2685. DetermineServerUpgradePath(
  2686. IN OUT PER_COMPONENT_DATA *pComp)
  2687. {
  2688. HRESULT hr;
  2689. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  2690. WCHAR *pwszDummy = NULL;
  2691. WCHAR *pwszSanitizedCAName = NULL;
  2692. LPWSTR pwszB2PolicyGuid = NULL;
  2693. DWORD dwVersion;
  2694. if (CS_UPGRADE_UNKNOWN != pComp->UpgradeFlag)
  2695. {
  2696. // already know upgrade type
  2697. CSASSERT(pServer->pwszSanitizedName); // this is a side-effect of this fxn, better have been set already
  2698. return S_OK;
  2699. }
  2700. // get active ca name
  2701. hr = myGetCertRegStrValue(
  2702. NULL,
  2703. NULL,
  2704. NULL,
  2705. wszREGACTIVE,
  2706. &pwszSanitizedCAName);
  2707. if (hr != S_OK)
  2708. {
  2709. BOOL fFinishCYS;
  2710. //for W2K after, it is possible to be in post mode
  2711. hr = CheckPostBaseInstallStatus(&fFinishCYS);
  2712. if (S_OK == hr && !fFinishCYS)
  2713. {
  2714. //this could be either w2k or whistler
  2715. //treat as whistler since upgrade path won't execute
  2716. pComp->UpgradeFlag = CS_UPGRADE_WHISTLER;
  2717. goto done;
  2718. }
  2719. // wszREGACTIVE used in Win2k product and after. If not found, this is way before our time
  2720. // make sure by grabbing wszREGSP4DEFAULTCONFIGURATION
  2721. LPWSTR pwszTmp = NULL;
  2722. hr = myGetCertRegStrValue(
  2723. NULL,
  2724. NULL,
  2725. NULL,
  2726. wszREGSP4DEFAULTCONFIGURATION,
  2727. &pwszTmp);
  2728. if (pwszTmp)
  2729. LocalFree(pwszTmp);
  2730. // error! bail, we have no idea what we're seeing
  2731. _JumpIfError(hr, error, "myGetCertRegStrValue wszREGSP4DEFAULTCONFIGURATION");
  2732. // hr == S_OK: yep, looks like valid NT4 installation
  2733. pComp->UpgradeFlag = CS_UPGRADE_UNSUPPORTED;
  2734. CSILOG(S_OK, IDS_LOG_UPGRADE_UNSUPPORTED, NULL, NULL, NULL);
  2735. _JumpError(hr, error, "myGetCertRegStrValue");
  2736. }
  2737. // check wszREGVERSION to get current version
  2738. hr = myGetCertRegDWValue(
  2739. NULL,
  2740. NULL,
  2741. NULL,
  2742. wszREGVERSION,
  2743. &dwVersion);
  2744. if (S_OK != hr && HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)!= hr)
  2745. {
  2746. _JumpErrorStr(hr, error, "myGetCertRegDWValue", wszREGVERSION);
  2747. }
  2748. // now either OK or FILE_NOT_FOUND
  2749. if (S_OK == hr)
  2750. {
  2751. // pComp->UpgradeFlag = SOME_FUNCTION(dwVersion); // CS_UPGRADE_WHISTLER already set as default; in future, key off of this
  2752. pComp->UpgradeFlag = CS_UPGRADE_WHISTLER;
  2753. CSILOG(S_OK, IDS_LOG_UPGRADE_B2B, NULL, NULL, NULL);
  2754. }
  2755. else
  2756. {
  2757. // FILE_NOT_FOUND: now we know it's (NT5 Beta 2 <= X < Whistler)
  2758. // is this Win2k, or NT5 Beta? Test for active policy module to have "ICertManageModule" entry
  2759. // check nt5 beta 2 and get active policy name
  2760. hr = myGetCertRegStrValue(
  2761. pwszSanitizedCAName,
  2762. wszREGKEYPOLICYMODULES,
  2763. NULL,
  2764. wszREGACTIVE,
  2765. &pwszB2PolicyGuid);
  2766. if (S_OK == hr)
  2767. {
  2768. hr = myGetCertRegStrValue(
  2769. wszREGKEYPOLICYMODULES,
  2770. pwszB2PolicyGuid,
  2771. NULL,
  2772. wszREGB2ICERTMANAGEMODULE,
  2773. &pwszDummy);
  2774. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  2775. {
  2776. // this doesn't exist on Win2k
  2777. pComp->UpgradeFlag = CS_UPGRADE_WIN2000;
  2778. CSILOG(S_OK, IDS_LOG_UPGRADE_WIN2000, NULL, NULL, NULL);
  2779. }
  2780. else
  2781. {
  2782. // this is definitely beta 2
  2783. pComp->UpgradeFlag = CS_UPGRADE_UNSUPPORTED;
  2784. CSILOG(S_OK, IDS_LOG_UPGRADE_UNSUPPORTED, NULL, NULL, NULL);
  2785. }
  2786. }
  2787. else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  2788. {
  2789. // strange, maybe no active module. Assume OK, latest bits.
  2790. pComp->UpgradeFlag = CS_UPGRADE_WIN2000;
  2791. CSILOG(S_OK, IDS_LOG_UPGRADE_WIN2000, NULL, NULL, NULL);
  2792. }
  2793. else
  2794. {
  2795. // other failure, just bail
  2796. _JumpErrorStr(hr, error, "myGetCertRegStrValue",
  2797. wszREGKEYPOLICYMODULES);
  2798. }
  2799. } // wszREGVERSION: FILE_NOT_FOUND
  2800. // take sanitized name
  2801. if (NULL != pServer->pwszSanitizedName)
  2802. {
  2803. // this will free the default name
  2804. LocalFree(pServer->pwszSanitizedName);
  2805. }
  2806. pServer->pwszSanitizedName = pwszSanitizedCAName;
  2807. pwszSanitizedCAName = NULL;
  2808. done:
  2809. hr = S_OK;
  2810. error:
  2811. if (NULL != pwszDummy)
  2812. {
  2813. LocalFree(pwszDummy);
  2814. }
  2815. if (NULL != pwszSanitizedCAName)
  2816. {
  2817. LocalFree(pwszSanitizedCAName);
  2818. }
  2819. CSILOG(hr, IDS_LOG_UPGRADE_TYPE, NULL, NULL, (DWORD const *) &pComp->UpgradeFlag);
  2820. return hr;
  2821. }
  2822. // Description: load and determine necessary information for upgrade
  2823. // upgrade won't continue if any error
  2824. HRESULT
  2825. LoadAndDetermineServerUpgradeInfo(
  2826. IN OUT PER_COMPONENT_DATA *pComp)
  2827. {
  2828. HRESULT hr;
  2829. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  2830. WCHAR *pwszRevocationType = NULL;
  2831. DWORD dwNetscapeType;
  2832. BOOL fDummy;
  2833. ALG_ID idAlgDummy;
  2834. CSP_INFO CSPInfoDummy;
  2835. ENUM_CATYPES CATypeDummy;
  2836. WCHAR *pwszCommonName = NULL;
  2837. // initialize
  2838. ZeroMemory(&CSPInfoDummy, sizeof(CSPInfoDummy));
  2839. // load information for all upgrade scenarios
  2840. // csp
  2841. hr = myGetCertRegStrValue(
  2842. pServer->pwszSanitizedName,
  2843. wszREGKEYCSP,
  2844. NULL,
  2845. wszREGPROVIDER,
  2846. &CSPInfoDummy.pwszProvName);
  2847. if (S_OK == hr && NULL != CSPInfoDummy.pwszProvName)
  2848. {
  2849. if (NULL != pServer->pCSPInfo->pwszProvName)
  2850. {
  2851. // free default csp
  2852. LocalFree(pServer->pCSPInfo->pwszProvName);
  2853. }
  2854. // use reg one as default for upgrade
  2855. pServer->pCSPInfo->pwszProvName = CSPInfoDummy.pwszProvName;
  2856. }
  2857. else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  2858. {
  2859. _JumpErrorStr(hr, error, "myGetCertRegStrValue", wszREGPROVIDER);
  2860. }
  2861. hr = myGetCertRegDWValue(
  2862. pServer->pwszSanitizedName,
  2863. wszREGKEYCSP,
  2864. NULL,
  2865. wszREGPROVIDERTYPE,
  2866. &CSPInfoDummy.dwProvType);
  2867. if (S_OK == hr)
  2868. {
  2869. pServer->pCSPInfo->dwProvType = CSPInfoDummy.dwProvType;
  2870. }
  2871. else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  2872. {
  2873. _JumpErrorStr(hr, error, "myGetCertRegDWValue", wszREGPROVIDERTYPE);
  2874. }
  2875. hr = myGetCertRegDWValue(
  2876. pServer->pwszSanitizedName,
  2877. wszREGKEYCSP,
  2878. NULL,
  2879. wszMACHINEKEYSET,
  2880. (DWORD*)&CSPInfoDummy.fMachineKeyset);
  2881. if (S_OK == hr)
  2882. {
  2883. pServer->pCSPInfo->fMachineKeyset = CSPInfoDummy.fMachineKeyset;
  2884. }
  2885. else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  2886. {
  2887. _JumpErrorStr(hr, error, "myGetCertRegDWValue", wszMACHINEKEYSET);
  2888. }
  2889. hr = myGetCertRegDWValue(
  2890. pServer->pwszSanitizedName,
  2891. wszREGKEYCSP,
  2892. NULL,
  2893. wszHASHALGORITHM,
  2894. (DWORD*)&idAlgDummy);
  2895. if (S_OK == hr)
  2896. {
  2897. pServer->pHashInfo->idAlg = idAlgDummy;
  2898. }
  2899. else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  2900. {
  2901. _JumpIfErrorStr(hr, error, "myGetCertRegDWValue", wszHASHALGORITHM);
  2902. }
  2903. if (NULL != pServer->pCSPInfoList)
  2904. {
  2905. // BUG, this will never happen because csp info list is not loaded yet
  2906. // one more checking, make sure csp is installed
  2907. if (NULL == findCSPInfoFromList(
  2908. pServer->pCSPInfoList,
  2909. pServer->pCSPInfo->pwszProvName,
  2910. pServer->pCSPInfo->dwProvType))
  2911. {
  2912. // if not, this is a broken ca
  2913. hr = E_INVALIDARG;
  2914. _JumpErrorStr(hr, error, "findCSPInfoFromList",
  2915. pServer->pCSPInfo->pwszProvName);
  2916. }
  2917. }
  2918. // UseDS flag
  2919. hr = myGetCertRegDWValue(
  2920. pServer->pwszSanitizedName,
  2921. NULL,
  2922. NULL,
  2923. wszREGCAUSEDS,
  2924. (DWORD*)&fDummy);
  2925. if (S_OK == hr)
  2926. {
  2927. // use from reg
  2928. pServer->fUseDS = fDummy;
  2929. }
  2930. else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  2931. {
  2932. _JumpErrorStr(hr, error, "myGetCertRegDWValue", wszREGCAUSEDS);
  2933. }
  2934. // CACommonName
  2935. // this will be used for looking cert in store to determine ca DN info
  2936. hr = myGetCertRegStrValue(
  2937. pServer->pwszSanitizedName,
  2938. NULL,
  2939. NULL,
  2940. wszREGCOMMONNAME,
  2941. &pwszCommonName);
  2942. if (S_OK != hr && HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  2943. {
  2944. _JumpError(hr, error, "myGetCertRegStrValue");
  2945. }
  2946. else if ((HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) ||
  2947. (S_OK == hr && L'\0' == pwszCommonName[0]))
  2948. {
  2949. if (S_OK == hr && L'\0' == pwszCommonName[0])
  2950. {
  2951. // empty string, use snaitized name instead
  2952. LocalFree(pwszCommonName);
  2953. }
  2954. // in case empty or not found, use sanitized
  2955. pwszCommonName = (WCHAR*)LocalAlloc(LMEM_FIXED,
  2956. (wcslen(pServer->pwszSanitizedName) + 1) * sizeof(WCHAR));
  2957. _JumpIfOutOfMemory(hr, error, pwszCommonName);
  2958. wcscpy(pwszCommonName, pServer->pwszSanitizedName);
  2959. }
  2960. if (NULL != pServer->pwszCACommonName)
  2961. {
  2962. LocalFree(pServer->pwszCACommonName);
  2963. }
  2964. pServer->pwszCACommonName = pwszCommonName;
  2965. pwszCommonName = NULL;
  2966. // Collect CAType, DN info, dwCertNameId and upgrade ca cert
  2967. hr = DetermineCAInfoAndType(pComp);
  2968. _JumpIfError(hr, error, "DetermineCAInfoAndType");
  2969. // load following values for later
  2970. // check revocation type
  2971. hr = myGetCertRegDWValue(
  2972. pServer->pwszSanitizedName,
  2973. wszREGKEYPOLICYMODULES,
  2974. wszCLASS_CERTPOLICY,
  2975. wszREGREVOCATIONTYPE,
  2976. &pServer->dwRevocationFlags);
  2977. if(hr != S_OK)
  2978. {
  2979. pServer->dwRevocationFlags = pServer->fUseDS?
  2980. REVEXT_DEFAULT_DS : REVEXT_DEFAULT_NODS;
  2981. }
  2982. // following for web page creation
  2983. // load shared folder for ca cert file name creation
  2984. if (NULL != pServer->pwszSharedFolder)
  2985. {
  2986. // shouldn't happen but in case
  2987. LocalFree(pServer->pwszSharedFolder);
  2988. pServer->pwszSharedFolder = NULL;
  2989. }
  2990. hr = myGetCertRegStrValue(
  2991. NULL,
  2992. NULL,
  2993. NULL,
  2994. wszREGDIRECTORY,
  2995. &pServer->pwszSharedFolder);
  2996. if (S_OK == hr && L'\0' == pServer->pwszSharedFolder[0])
  2997. {
  2998. // in case of empty, set to null
  2999. LocalFree(pServer->pwszSharedFolder);
  3000. pServer->pwszSharedFolder = NULL;
  3001. }
  3002. else if (S_OK != hr && HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  3003. {
  3004. _JumpError(hr, error, "myGetCertRegStrValue");
  3005. }
  3006. // build ca cert file name for web install and ca cert saving
  3007. if (NULL != pServer->pwszCACertFile)
  3008. {
  3009. // free old one
  3010. LocalFree(pServer->pwszCACertFile);
  3011. }
  3012. hr = csiBuildCACertFileName(
  3013. pComp->hInstance,
  3014. NULL, //hwnd, ok for upgrade
  3015. pComp->fUnattended,
  3016. pServer->pwszSharedFolder,
  3017. pServer->pwszSanitizedName,
  3018. L".crt",
  3019. 0, // iCert
  3020. &pServer->pwszCACertFile);
  3021. _JumpIfError(hr, error, "BuildCACertFileName");
  3022. hr = S_OK;
  3023. error:
  3024. if (NULL != pwszRevocationType)
  3025. {
  3026. LocalFree(pwszRevocationType);
  3027. }
  3028. if (NULL != pwszCommonName)
  3029. {
  3030. LocalFree(pwszCommonName);
  3031. }
  3032. return hr;
  3033. }
  3034. HRESULT
  3035. GetConfigInSharedFolderWithCert(
  3036. WCHAR const *pwszSharedFolder,
  3037. OUT WCHAR **ppwszConfig)
  3038. {
  3039. HRESULT hr;
  3040. ICertConfig * pICertConfig = NULL;
  3041. BSTR bstrConfig = NULL;
  3042. BOOL fCoInit = FALSE;
  3043. WCHAR *pwszCAMachine;
  3044. WCHAR *pwszCAName;
  3045. WCHAR wszCertFileInSharedFolder[MAX_PATH];
  3046. LONG i;
  3047. LONG lCount;
  3048. LONG Index;
  3049. BOOL fLocal;
  3050. CSASSERT(NULL != ppwszConfig);
  3051. *ppwszConfig = NULL;
  3052. hr = CoInitialize(NULL);
  3053. if (S_OK != hr && S_FALSE != hr)
  3054. {
  3055. _JumpError(hr, error, "CoInitialize");
  3056. }
  3057. fCoInit = TRUE;
  3058. hr = CoCreateInstance(
  3059. CLSID_CCertConfig,
  3060. NULL,
  3061. CLSCTX_INPROC_SERVER,
  3062. IID_ICertConfig,
  3063. (VOID**) &pICertConfig);
  3064. _JumpIfError(hr, error, "CoCreateInstance");
  3065. // get local
  3066. hr = pICertConfig->Reset(0, &lCount);
  3067. _JumpIfError(hr, error, "ICertConfig->Reset");
  3068. for (i = 0; i < lCount; ++i)
  3069. {
  3070. hr = pICertConfig->Next(&Index);
  3071. if (S_OK != hr && S_FALSE != hr)
  3072. {
  3073. _JumpError(hr, error, "ICertConfig->Next");
  3074. }
  3075. if (-1 == Index)
  3076. {
  3077. hr = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
  3078. _JumpError(hr, error, "No CA cert file");
  3079. }
  3080. hr = pICertConfig->GetField(wszCONFIG_CONFIG, &bstrConfig);
  3081. _JumpIfError(hr, error, "ICertConfig->GetField(Config)");
  3082. pwszCAMachine = (WCHAR*)bstrConfig;
  3083. pwszCAName = wcschr(pwszCAMachine, L'\\');
  3084. if (NULL == pwszCAName)
  3085. {
  3086. hr = E_INVALIDARG;
  3087. _JumpError(hr, error, "Invalid config string");
  3088. }
  3089. pwszCAName[0] = '\0'; // make pwszCAMachine
  3090. ++pwszCAName;
  3091. // form NT4 ca cert file path in shared folder
  3092. wcscpy(wszCertFileInSharedFolder, pwszSharedFolder);
  3093. wcscat(wszCertFileInSharedFolder, L"\\");
  3094. wcscat(wszCertFileInSharedFolder, pwszCAMachine);
  3095. wcscat(wszCertFileInSharedFolder, L"_");
  3096. wcscat(wszCertFileInSharedFolder, pwszCAName);
  3097. wcscat(wszCertFileInSharedFolder, L".crt");
  3098. DBGPRINT((
  3099. DBG_SS_CERTOCM,
  3100. "wszCertFileInSharedFolder: %ws\n",
  3101. wszCertFileInSharedFolder));
  3102. if (myDoesFileExist(wszCertFileInSharedFolder))
  3103. {
  3104. //done
  3105. break;
  3106. }
  3107. SysFreeString(bstrConfig);
  3108. bstrConfig = NULL;
  3109. }
  3110. if (i >= lCount)
  3111. {
  3112. hr = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
  3113. _JumpError(hr, error, "No CA cert file");
  3114. }
  3115. *ppwszConfig = (WCHAR*)LocalAlloc(LMEM_FIXED,
  3116. SysStringByteLen(bstrConfig) + sizeof(WCHAR));
  3117. _JumpIfOutOfMemory(hr, error, *ppwszConfig);
  3118. wcscpy(*ppwszConfig, bstrConfig);
  3119. hr = S_OK;
  3120. error:
  3121. if (NULL != pICertConfig)
  3122. {
  3123. pICertConfig->Release();
  3124. }
  3125. if (NULL != bstrConfig)
  3126. {
  3127. SysFreeString(bstrConfig);
  3128. }
  3129. if (fCoInit)
  3130. {
  3131. CoUninitialize();
  3132. }
  3133. return hr;
  3134. }
  3135. HRESULT
  3136. DetermineClientUpgradePath(
  3137. IN OUT PER_COMPONENT_DATA *pComp)
  3138. {
  3139. HRESULT hr;
  3140. CAWEBCLIENTSETUPINFO *pClient = pComp->CA.pClient;
  3141. WCHAR *pwszCAName;
  3142. DWORD dwVersion;
  3143. if (CS_UPGRADE_UNKNOWN != pComp->UpgradeFlag)
  3144. {
  3145. // already know upgrade type
  3146. CSASSERT(pClient->pwszWebCAMachine); // this is a side-effect of this fxn, better have been set already
  3147. CSASSERT(pClient->pwszWebCAName); // this is a side-effect of this fxn, better have been set already
  3148. return S_OK;
  3149. }
  3150. //get ca info from registry here
  3151. if (NULL != pClient->pwszWebCAMachine)
  3152. {
  3153. // shouldn't happen, just in case
  3154. LocalFree(pClient->pwszWebCAMachine);
  3155. pClient->pwszWebCAMachine = NULL;
  3156. }
  3157. if (NULL != pClient->pwszWebCAName)
  3158. {
  3159. // shouldn't happen, just in case
  3160. LocalFree(pClient->pwszWebCAName);
  3161. pClient->pwszWebCAName = NULL;
  3162. }
  3163. // get ca machine
  3164. hr = myGetCertRegStrValue(
  3165. NULL,
  3166. NULL,
  3167. NULL,
  3168. wszREGWEBCLIENTCAMACHINE,
  3169. &pClient->pwszWebCAMachine);
  3170. if (S_OK != hr || L'\0' == pClient->pwszWebCAMachine[0])
  3171. {
  3172. BOOL fFinishCYS;
  3173. //for W2K after, it is possible to be in post mode
  3174. hr = CheckPostBaseInstallStatus(&fFinishCYS);
  3175. if (S_OK == hr && !fFinishCYS)
  3176. {
  3177. //this could be either w2k or whistler
  3178. //treat as whistler since upgrade path won't execute
  3179. pComp->UpgradeFlag = CS_UPGRADE_WHISTLER;
  3180. goto done;
  3181. }
  3182. // incorrect reg state,
  3183. // either not found entry or empty string: NT4
  3184. pComp->UpgradeFlag = CS_UPGRADE_UNSUPPORTED;
  3185. hr = S_OK;
  3186. CSILOG(S_OK, IDS_LOG_UPGRADE_UNSUPPORTED, NULL, NULL, NULL);
  3187. _JumpErrorStr(hr, error, "myGetCertRegStrValue", wszREGWEBCLIENTCAMACHINE);
  3188. }
  3189. // get ca
  3190. hr = myGetCertRegStrValue(
  3191. NULL,
  3192. NULL,
  3193. NULL,
  3194. wszREGWEBCLIENTCANAME,
  3195. &pClient->pwszWebCAName);
  3196. if (S_OK != hr || L'\0' == pClient->pwszWebCAName[0])
  3197. {
  3198. // incorrect reg state,
  3199. // either not found entry or empty string: NT4
  3200. if (pClient->pwszWebCAMachine)
  3201. LocalFree(pClient->pwszWebCAMachine);
  3202. pComp->UpgradeFlag = CS_UPGRADE_UNSUPPORTED;
  3203. hr = S_OK;
  3204. CSILOG(S_OK, IDS_LOG_UPGRADE_UNSUPPORTED, NULL, NULL, NULL);
  3205. _JumpErrorStr(hr, error, "myGetCertRegStrValue", wszREGWEBCLIENTCANAME);
  3206. }
  3207. // Now either W2k or Whistler
  3208. // check wszREGVERSION to get current version on Whistler++
  3209. hr = myGetCertRegDWValue(
  3210. NULL,
  3211. NULL,
  3212. NULL,
  3213. wszREGVERSION,
  3214. &dwVersion);
  3215. if (S_OK != hr && HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)!= hr)
  3216. {
  3217. _JumpErrorStr(hr, error, "myGetCertRegDWValue", wszREGVERSION);
  3218. }
  3219. // now either OK or FILE_NOT_FOUND
  3220. if (S_OK == hr)
  3221. {
  3222. // pComp->UpgradeFlag = SOME_FUNCTION(dwVersion); // CS_UPGRADE_WHISTLER already set as default; in future, key off of this
  3223. pComp->UpgradeFlag = CS_UPGRADE_WHISTLER;
  3224. CSILOG(S_OK, IDS_LOG_UPGRADE_B2B, NULL, NULL, NULL);
  3225. }
  3226. else
  3227. {
  3228. pComp->UpgradeFlag = CS_UPGRADE_WIN2000;
  3229. CSILOG(S_OK, IDS_LOG_UPGRADE_WIN2000, NULL, NULL, NULL);
  3230. }
  3231. done:
  3232. hr = S_OK;
  3233. error:
  3234. CSILOG(hr, IDS_LOG_UPGRADE_TYPE, NULL, NULL, (DWORD const *) &pComp->UpgradeFlag);
  3235. return hr;
  3236. }
  3237. HRESULT
  3238. LoadAndDetermineClientUpgradeInfo(
  3239. IN OUT PER_COMPONENT_DATA *pComp)
  3240. {
  3241. HRESULT hr;
  3242. CAWEBCLIENTSETUPINFO *pClient = pComp->CA.pClient;
  3243. WCHAR *pwszCAName;
  3244. DWORD dwVersion;
  3245. //get ca info from registry here
  3246. if (NULL != pClient->pwszSanitizedWebCAName)
  3247. {
  3248. // shouldn't happen, just in case
  3249. LocalFree(pClient->pwszSanitizedWebCAName);
  3250. pClient->pwszSanitizedWebCAName = NULL;
  3251. }
  3252. hr = DetermineClientUpgradePath(pComp);
  3253. _JumpIfError(hr, error, "DetermineClientUpgradePath");
  3254. // get ca
  3255. hr = myGetCertRegDWValue(
  3256. NULL,
  3257. NULL,
  3258. NULL,
  3259. wszREGWEBCLIENTCATYPE,
  3260. (DWORD *) &pClient->WebCAType);
  3261. _PrintIfErrorStr(hr, "myGetCertRegDWValue", wszREGWEBCLIENTCATYPE);
  3262. hr = mySanitizeName(pClient->pwszWebCAName,
  3263. &pClient->pwszSanitizedWebCAName);
  3264. _JumpIfError(hr, error, "mySanitizeName");
  3265. hr = S_OK;
  3266. error:
  3267. CSILOG(hr, IDS_LOG_UPGRADE_TYPE, NULL, NULL, (DWORD const *) &pComp->UpgradeFlag);
  3268. return hr;
  3269. }
  3270. // apply ACL to key container for all upgrade scenarios
  3271. HRESULT
  3272. UpgradeKeyContainerSecurity(
  3273. HWND hwnd,
  3274. PER_COMPONENT_DATA *pComp)
  3275. {
  3276. HRESULT hr;
  3277. HCRYPTPROV hProv = NULL;
  3278. WCHAR *pwszProvName = NULL;
  3279. DWORD dwProvType;
  3280. ALG_ID idAlg;
  3281. BOOL fMachineKeyset;
  3282. // get prov name
  3283. hr = myGetCertSrvCSP(
  3284. FALSE, // fEncryptionCSP
  3285. pComp->CA.pServer->pwszSanitizedName,
  3286. &dwProvType,
  3287. &pwszProvName,
  3288. &idAlg,
  3289. &fMachineKeyset,
  3290. NULL); // pdwKeySize
  3291. _JumpIfError(hr, error, "myGetCertSrvCSP");
  3292. if (!myCertSrvCryptAcquireContext(&hProv,
  3293. pComp->CA.pServer->pwszSanitizedName,
  3294. pwszProvName,
  3295. dwProvType,
  3296. CRYPT_SILENT, // get key, upgrade, no UI
  3297. fMachineKeyset))
  3298. {
  3299. hr = myHLastError();
  3300. _JumpError(hr, error, "myCertSrvCryptAcquireContext");
  3301. }
  3302. // set acl on it
  3303. hr = csiSetKeyContainerSecurity(hProv);
  3304. _JumpIfError(hr, error, "csiSetKeyContainerSecurity");
  3305. error:
  3306. if (NULL != hProv)
  3307. {
  3308. CryptReleaseContext(hProv, 0);
  3309. }
  3310. if (NULL != pwszProvName)
  3311. {
  3312. LocalFree(pwszProvName);
  3313. }
  3314. CSILOG(hr, IDS_LOG_UPGRADE_KEY_SECURITY, NULL, NULL, NULL);
  3315. return hr;
  3316. }
  3317. HRESULT InstallNewTemplates(HWND hwnd)
  3318. {
  3319. HRESULT hr = S_OK;
  3320. SHELLEXECUTEINFO shi;
  3321. ZeroMemory(&shi, sizeof(shi));
  3322. shi.cbSize = sizeof(shi);
  3323. shi.hwnd = hwnd;
  3324. shi.lpVerb = SZ_VERB_OPEN;
  3325. shi.lpFile = SZ_REGSVR32;
  3326. shi.lpParameters = SZ_REGSVR32_CERTCLI;
  3327. shi.fMask = SEE_MASK_FLAG_NO_UI |
  3328. SEE_MASK_NOCLOSEPROCESS;
  3329. if(!ShellExecuteEx(&shi))
  3330. {
  3331. hr = myHLastError();
  3332. _JumpError(hr, error, "ShellExecuteEx");
  3333. }
  3334. if(WAIT_FAILED == WaitForSingleObject(shi.hProcess, INFINITE))
  3335. {
  3336. hr = myHLastError();
  3337. _JumpError(hr, error, "WaitForSingleObject");
  3338. }
  3339. error:
  3340. if(shi.hProcess)
  3341. {
  3342. CloseHandle(shi.hProcess);
  3343. }
  3344. return hr;
  3345. }
  3346. HRESULT
  3347. UpgradeServer(
  3348. IN HWND hwnd,
  3349. IN PER_COMPONENT_DATA *pComp)
  3350. {
  3351. HRESULT hr;
  3352. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  3353. hr = RegisterAndUnRegisterDLLs(RD_SERVER|RD_SKIPUNREGMMC, pComp, hwnd);
  3354. _JumpIfError(hr, error, "RegisterAndUnRegisterDLLs");
  3355. hr = LoadAndDetermineServerUpgradeInfo(pComp);
  3356. _JumpIfError(hr, error, "LoadAndDetermineServerUpgradeInfo");
  3357. // create enroll dir
  3358. hr = CreateCertsrvDirectories(pComp, TRUE, TRUE);
  3359. _JumpIfError(hr, error, "CreateCertsrvDirectories");
  3360. hr = EnableVRootsAndShares(FALSE, TRUE, TRUE, pComp);
  3361. _PrintIfError(hr, "EnableVRootsAndShares(share only)");
  3362. hr = UpgradeServerRegEntries(hwnd, pComp);
  3363. _JumpIfError(hr, error, "UpgradeServerRegEntries");
  3364. hr = CreateCertWebIncPages(hwnd, pComp, TRUE /*IsServer*/, TRUE);
  3365. _JumpIfError(hr, error, "CreateCertWebIncPages");
  3366. hr = RenameMiscTargets(hwnd, pComp, TRUE);
  3367. _JumpIfError(hr, error, "RenameMiscTargets");
  3368. hr = UpgradeKeyContainerSecurity(hwnd, pComp);
  3369. // ignore new acl failure
  3370. _PrintIfError(hr, "UpgradeKeyContainerSecurity");
  3371. // always register dcom
  3372. hr = RegisterDcomServer(
  3373. CLSID_CCertRequestD,
  3374. wszREQUESTFRIENDLYNAME,
  3375. wszREQUESTVERINDPROGID,
  3376. wszREQUESTPROGID);
  3377. _JumpIfError(hr, error, "RegisterDcomServer");
  3378. hr = RegisterDcomServer(
  3379. CLSID_CCertAdminD,
  3380. wszADMINFRIENDLYNAME,
  3381. wszADMINVERINDPROGID,
  3382. wszADMINPROGID);
  3383. _JumpIfError(hr, error, "RegisterDcomServer");
  3384. hr = RegisterDcomApp(CLSID_CCertRequestD);
  3385. _JumpIfError(hr, error, "RegisterDcomApp");
  3386. // fix for 155772 Certsrv: After upgrading a 2195 Enterprise Root CA
  3387. // to 2254.01VBL03 the CA will no longer issue Certs
  3388. hr = InstallNewTemplates(hwnd);
  3389. _JumpIfError(hr, error, "InstallNewTemplates");
  3390. // always fix certsvc in upgrade
  3391. hr = FixCertsvcService(pComp);
  3392. _PrintIfError(hr, "FixCertsvcService");
  3393. // delete any old program groups
  3394. DeleteProgramGroups(TRUE, pComp);
  3395. hr = CreateProgramGroups(FALSE, pComp, hwnd);
  3396. _PrintIfError(hr, "CreateProgramGroups");
  3397. // delete old stuff
  3398. DeleteOldFilesAndDirectories(pComp);
  3399. DBGPRINT((DBG_SS_CERTOCM, "UpgradeServer: setting SETUP_SERVER_UPGRADED_FLAG\n"));
  3400. hr = SetSetupStatus(NULL, SETUP_SERVER_UPGRADED_FLAG, TRUE);
  3401. _JumpIfError(hr, error, "SetSetupStatus");
  3402. hr = csiUpgradeCertSrvSecurity(
  3403. pServer->pwszSanitizedName,
  3404. IsEnterpriseCA(pServer->CAType)?true:false,
  3405. pServer->fUseDS?true:false,
  3406. pComp->UpgradeFlag);
  3407. if (hr == HRESULT_FROM_WIN32(ERROR_CAN_NOT_COMPLETE))
  3408. {
  3409. _PrintError(hr, "csiUpgradeCertSrvSecurity marked for later fixup; error ignored");
  3410. hr = S_OK;
  3411. }
  3412. _JumpIfError(hr, error, "csiUpgradeCertSrvSecurity");
  3413. hr = S_OK;
  3414. error:
  3415. CSILOG(hr, IDS_LOG_UPGRADE_SERVER, NULL, NULL, NULL);
  3416. return hr;
  3417. }
  3418. HRESULT
  3419. UpgradeClient(
  3420. IN HWND hwnd,
  3421. IN PER_COMPONENT_DATA *pComp)
  3422. {
  3423. HRESULT hr;
  3424. CAWEBCLIENTSETUPINFO *pClient = pComp->CA.pClient;
  3425. if ((IS_CLIENT_UPGRADE & pComp->dwInstallStatus) &&
  3426. (IS_SERVER_UPGRADE & pComp->dwInstallStatus))
  3427. {
  3428. // upgrade server will also hit here so skip it
  3429. goto done;
  3430. }
  3431. // unset client
  3432. hr = SetSetupStatus(NULL, SETUP_CLIENT_FLAG, FALSE);
  3433. _JumpIfError(hr, error, "SetSetupStatus");
  3434. hr = RegisterAndUnRegisterDLLs(RD_CLIENT|RD_SKIPUNREGMMC, pComp, hwnd);
  3435. _JumpIfError(hr, error, "RegisterAndUnRegisterDLLs");
  3436. hr = LoadAndDetermineClientUpgradeInfo(pComp);
  3437. _JumpIfError(hr, error, "LoadAndDetermineClientUpgradeInfo");
  3438. hr = UpgradeWebClientRegEntries(pComp);
  3439. _JumpIfError(hr, error, "UpgradeWebClientRegEntries");
  3440. hr = CreateCertWebIncPages(hwnd, pComp, FALSE /*IsServer*/, TRUE);
  3441. _JumpIfError(hr, error, "CreateCertWebIncPages");
  3442. hr = RenameMiscTargets(hwnd, pComp, FALSE);
  3443. _JumpIfError(hr, error, "RenameMiscTargets");
  3444. // delete any old program groups
  3445. DeleteProgramGroups(FALSE, pComp);
  3446. hr = CreateProgramGroups(TRUE, pComp, hwnd);
  3447. _PrintIfError(hr, "CreateProgramGroups");
  3448. hr = SetSetupStatus(NULL, SETUP_CLIENT_FLAG, TRUE);
  3449. _JumpIfError(hr, error, "SetSetupStatus");
  3450. DeleteOldFilesAndDirectories(pComp);
  3451. done:
  3452. hr = S_OK;
  3453. error:
  3454. CSILOG(hr, IDS_LOG_UPGRADE_CLIENT, NULL, NULL, NULL);
  3455. return hr;
  3456. }
  3457. HRESULT
  3458. GetServerNames(
  3459. IN HWND hwnd,
  3460. IN HINSTANCE hInstance,
  3461. IN BOOL fUnattended,
  3462. OUT WCHAR **ppwszServerName,
  3463. OUT WCHAR **ppwszServerNameOld)
  3464. {
  3465. HRESULT hr;
  3466. // Retrieve computer name strings.
  3467. hr = myGetComputerNames(ppwszServerName, ppwszServerNameOld);
  3468. if (S_OK != hr)
  3469. {
  3470. CertErrorMessageBox(
  3471. hInstance,
  3472. fUnattended,
  3473. hwnd,
  3474. IDS_ERR_GETCOMPUTERNAME,
  3475. hr,
  3476. NULL);
  3477. _JumpError(hr, error, "myGetComputerNames");
  3478. }
  3479. error:
  3480. return(hr);
  3481. }
  3482. HRESULT
  3483. UpdateDomainAndUserName(
  3484. IN HWND hwnd,
  3485. IN OUT PER_COMPONENT_DATA *pComp)
  3486. {
  3487. HRESULT hr;
  3488. // free old server and installer info because we might get them in nt base
  3489. if (NULL != pComp->pwszServerName)
  3490. {
  3491. LocalFree(pComp->pwszServerName);
  3492. pComp->pwszServerName = NULL;
  3493. }
  3494. if (NULL != pComp->pwszServerNameOld)
  3495. {
  3496. LocalFree(pComp->pwszServerNameOld);
  3497. pComp->pwszServerNameOld = NULL;
  3498. }
  3499. hr = GetServerNames(
  3500. hwnd,
  3501. pComp->hInstance,
  3502. pComp->fUnattended,
  3503. &pComp->pwszServerName,
  3504. &pComp->pwszServerNameOld);
  3505. _JumpIfError(hr, error, "GetServerNames");
  3506. DBGPRINT((DBG_SS_CERTOCM, "UpdateDomainAndUserName:%ws,%ws\n", pComp->pwszServerName, pComp->pwszServerNameOld));
  3507. DumpBackTrace("UpdateDomainAndUserName");
  3508. error:
  3509. return(hr);
  3510. }
  3511. HRESULT
  3512. StopCertService(
  3513. IN HWND hwnd,
  3514. IN SC_HANDLE hSC,
  3515. IN WCHAR const *pwszServiceName)
  3516. {
  3517. HRESULT hr;
  3518. SERVICE_STATUS status;
  3519. DWORD dwAttempt;
  3520. if (!ControlService(hSC, SERVICE_CONTROL_STOP, &status))
  3521. {
  3522. hr = myHLastError();
  3523. if (HRESULT_FROM_WIN32(ERROR_SERVICE_NOT_ACTIVE) != hr)
  3524. {
  3525. _JumpErrorStr(hr, error, "ControlService(Stop)", pwszServiceName);
  3526. }
  3527. }
  3528. // get out after it is really stopped
  3529. for (dwAttempt = 0; dwAttempt < CERT_MAX_ATTEMPT; dwAttempt++)
  3530. {
  3531. DBGCODE(status.dwCurrentState = -1);
  3532. if (!QueryServiceStatus(hSC, &status))
  3533. {
  3534. // query failed, ignore error
  3535. hr = S_OK;
  3536. _JumpErrorStr(
  3537. myHLastError(), // Display ignored error
  3538. error,
  3539. "QueryServiceStatus",
  3540. pwszServiceName);
  3541. }
  3542. if (status.dwCurrentState != SERVICE_STOP_PENDING &&
  3543. status.dwCurrentState != SERVICE_RUNNING)
  3544. {
  3545. // it was stopped already
  3546. break;
  3547. }
  3548. DBGPRINT((
  3549. DBG_SS_CERTOCM,
  3550. "Stopping %ws service: current state=%d\n",
  3551. pwszServiceName,
  3552. status.dwCurrentState));
  3553. Sleep(CERT_HALF_SECOND);
  3554. }
  3555. if (dwAttempt >= CERT_MAX_ATTEMPT)
  3556. {
  3557. DBGPRINT((
  3558. DBG_SS_CERTOCM,
  3559. "Timeout stopping %ws service: current state=%d\n",
  3560. pwszServiceName,
  3561. status.dwCurrentState));
  3562. }
  3563. else
  3564. {
  3565. DBGPRINT((
  3566. DBG_SS_CERTOCM,
  3567. "Stopped %ws service\n",
  3568. pwszServiceName));
  3569. }
  3570. hr = S_OK;
  3571. error:
  3572. CSILOG(hr, IDS_LOG_SERVICE_STOPPED, pwszServiceName, NULL, NULL);
  3573. return(hr);
  3574. }
  3575. HRESULT
  3576. GetServiceControl(
  3577. WCHAR const *pwszServiceName,
  3578. OUT SC_HANDLE *phService)
  3579. {
  3580. HRESULT hr;
  3581. SC_HANDLE hSCManager = NULL;
  3582. *phService = NULL;
  3583. hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  3584. if (NULL == hSCManager)
  3585. {
  3586. hr = myHLastError();
  3587. _JumpError(hr, error, "OpenSCManager");
  3588. }
  3589. *phService = OpenService(hSCManager, pwszServiceName, SERVICE_ALL_ACCESS);
  3590. if (NULL == *phService)
  3591. {
  3592. hr = myHLastError();
  3593. _JumpErrorStr2(
  3594. hr,
  3595. error,
  3596. "OpenService",
  3597. pwszServiceName,
  3598. HRESULT_FROM_WIN32(ERROR_SERVICE_DOES_NOT_EXIST));
  3599. }
  3600. hr = S_OK;
  3601. error:
  3602. if (NULL != hSCManager)
  3603. {
  3604. CloseServiceHandle(hSCManager);
  3605. }
  3606. return hr;
  3607. }
  3608. HRESULT
  3609. IsServiceRunning(
  3610. IN SC_HANDLE const hSCService,
  3611. OUT BOOL *pfRun)
  3612. {
  3613. HRESULT hr;
  3614. SERVICE_STATUS status;
  3615. *pfRun = FALSE;
  3616. if (!QueryServiceStatus(hSCService, &status))
  3617. {
  3618. hr = myHLastError();
  3619. _JumpError(hr, error, "QueryServiceStatus");
  3620. }
  3621. if (SERVICE_STOPPED != status.dwCurrentState &&
  3622. SERVICE_STOP_PENDING != status.dwCurrentState)
  3623. {
  3624. *pfRun = TRUE;
  3625. }
  3626. hr = S_OK;
  3627. error:
  3628. return hr;
  3629. }
  3630. HRESULT
  3631. StartAndStopService(
  3632. IN HINSTANCE hInstance,
  3633. IN BOOL fUnattended,
  3634. IN HWND const hwnd,
  3635. IN WCHAR const *pwszServiceName,
  3636. IN BOOL const fStopService,
  3637. IN BOOL const fConfirm,
  3638. IN int iMsg,
  3639. OUT BOOL *pfServiceWasRunning)
  3640. {
  3641. HRESULT hr;
  3642. SC_HANDLE hService = NULL;
  3643. SERVICE_STATUS status;
  3644. *pfServiceWasRunning = FALSE;
  3645. hr = GetServiceControl(pwszServiceName, &hService);
  3646. if (S_OK != hr)
  3647. {
  3648. _PrintError2(
  3649. hr,
  3650. "GetServiceControl",
  3651. HRESULT_FROM_WIN32(ERROR_SERVICE_DOES_NOT_EXIST));
  3652. if (HRESULT_FROM_WIN32(ERROR_SERVICE_DOES_NOT_EXIST) == hr)
  3653. {
  3654. hr = S_OK;
  3655. }
  3656. goto error;
  3657. }
  3658. // to get status if the service is running
  3659. hr = IsServiceRunning(hService, pfServiceWasRunning);
  3660. _JumpIfError(hr, error, "IsServiceRunning");
  3661. if (fStopService)
  3662. {
  3663. if (*pfServiceWasRunning)
  3664. {
  3665. // stop the service
  3666. if (fConfirm)
  3667. {
  3668. // confirmation dialog
  3669. int ret = CertMessageBox(
  3670. hInstance,
  3671. fUnattended,
  3672. hwnd,
  3673. iMsg,
  3674. 0,
  3675. MB_YESNO |
  3676. MB_ICONWARNING |
  3677. CMB_NOERRFROMSYS,
  3678. NULL);
  3679. if (IDYES != ret)
  3680. {
  3681. hr = E_ABORT;
  3682. _JumpError(hr, error, "Cancel it");
  3683. }
  3684. }
  3685. hr = StopCertService(hwnd, hService, pwszServiceName);
  3686. _JumpIfErrorStr(hr, error, "StopCertService", pwszServiceName);
  3687. }
  3688. }
  3689. else
  3690. {
  3691. // START the service
  3692. if (!*pfServiceWasRunning)
  3693. {
  3694. if (!StartService(hService, 0, NULL))
  3695. {
  3696. hr = myHLastError();
  3697. _JumpErrorStr(hr, error, "StartService", pwszServiceName);
  3698. }
  3699. }
  3700. }
  3701. hr = S_OK;
  3702. error:
  3703. if (NULL != hService)
  3704. {
  3705. CloseServiceHandle(hService);
  3706. }
  3707. CSILOG(
  3708. hr,
  3709. fStopService? IDS_LOG_SERVICE_STOPPED : IDS_LOG_SERVICE_STARTED,
  3710. pwszServiceName,
  3711. NULL,
  3712. NULL);
  3713. return hr;
  3714. }
  3715. // fix existing certsvc service to add/use new service description
  3716. HRESULT
  3717. FixCertsvcService(PER_COMPONENT_DATA *pComp)
  3718. {
  3719. HRESULT hr;
  3720. SC_HANDLE hService = NULL;
  3721. QUERY_SERVICE_CONFIG *pServiceConfig = NULL;
  3722. WCHAR *pwszServiceDesc = NULL;
  3723. WCHAR const *pwszDisplayName;
  3724. SERVICE_DESCRIPTION sd;
  3725. DWORD dwSize;
  3726. hr = GetServiceControl(wszSERVICE_NAME, &hService);
  3727. _JumpIfError(hr, error, "GetServiceControl");
  3728. // get size
  3729. if (!QueryServiceConfig(hService,
  3730. NULL,
  3731. 0,
  3732. &dwSize))
  3733. {
  3734. hr = myHLastError();
  3735. if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) != hr)
  3736. {
  3737. _JumpError(hr, fix_desc, "QueryServiceConfig");
  3738. }
  3739. }
  3740. else
  3741. {
  3742. // impossible???
  3743. hr = E_INVALIDARG;
  3744. _JumpError(hr, fix_desc, "QueryServiceConfig");
  3745. }
  3746. CSASSERT(0 < dwSize);
  3747. // allocate config buffer
  3748. pServiceConfig = (QUERY_SERVICE_CONFIG*)LocalAlloc(
  3749. LMEM_FIXED | LMEM_ZEROINIT,
  3750. dwSize);
  3751. _JumpIfOutOfMemory(hr, error, pServiceConfig);
  3752. // get config
  3753. if (!QueryServiceConfig(hService,
  3754. pServiceConfig,
  3755. dwSize,
  3756. &dwSize))
  3757. {
  3758. hr = myHLastError();
  3759. _JumpError(hr, fix_desc, "QueryServiceConfig");
  3760. }
  3761. // use new display name
  3762. pwszDisplayName = myLoadResourceString(IDS_CA_SERVICEDISPLAYNAME);
  3763. if (NULL == pwszDisplayName)
  3764. {
  3765. hr = myHLastError();
  3766. _JumpError(hr, error, "myLoadResourceString");
  3767. }
  3768. if (!ChangeServiceConfig(hService,
  3769. pServiceConfig->dwServiceType, //dwServiceType
  3770. SERVICE_NO_CHANGE, //dwStartType
  3771. SERVICE_NO_CHANGE, //dwErrorControl
  3772. NULL, //lpBinaryPathName
  3773. NULL, //lpLoadOrderGroup
  3774. NULL, //lpdwTagId
  3775. NULL, //lpDependences
  3776. NULL, //lpServiceStartName
  3777. NULL, //lpPassword
  3778. pwszDisplayName))
  3779. {
  3780. hr = myHLastError();
  3781. _JumpIfError(hr, fix_desc, "ChangeServiceConfig");
  3782. }
  3783. fix_desc:
  3784. // add description
  3785. hr = myLoadRCString(pComp->hInstance, IDS_CA_SERVICEDESCRIPTION, &pwszServiceDesc);
  3786. _JumpIfError(hr, error, "myLoadRCString");
  3787. sd.lpDescription = pwszServiceDesc;
  3788. if (!ChangeServiceConfig2(hService,
  3789. SERVICE_CONFIG_DESCRIPTION,
  3790. (VOID*)&sd))
  3791. {
  3792. hr = myHLastError();
  3793. _JumpError(hr, error, "ChangeServiceConfig2");
  3794. }
  3795. hr = S_OK;
  3796. error:
  3797. if (NULL != hService)
  3798. {
  3799. CloseServiceHandle(hService);
  3800. }
  3801. if (NULL != pwszServiceDesc)
  3802. {
  3803. LocalFree(pwszServiceDesc);
  3804. }
  3805. if (NULL != pServiceConfig)
  3806. {
  3807. LocalFree(pServiceConfig);
  3808. }
  3809. return hr;
  3810. }
  3811. HRESULT
  3812. PreUninstallCore(
  3813. IN HWND hwnd,
  3814. IN PER_COMPONENT_DATA *pComp,
  3815. IN BOOL fPreserveClient)
  3816. {
  3817. BOOL fDummy;
  3818. HRESULT hr;
  3819. DWORD dwFlags = RD_UNREGISTER;
  3820. hr = StartAndStopService(pComp->hInstance,
  3821. pComp->fUnattended,
  3822. hwnd,
  3823. wszSERVICE_NAME,
  3824. TRUE, // stop the service
  3825. FALSE, // no confirm
  3826. 0, //doesn't matter since no confirm
  3827. &fDummy);
  3828. _PrintIfError(hr, "StartAndStopService");
  3829. hr = RegisterAndUnRegisterDLLs(dwFlags, pComp, hwnd);
  3830. _PrintIfError(hr, "RegisterAndUnRegisterDLLs");
  3831. hr = S_OK;
  3832. return(hr);
  3833. }
  3834. VOID
  3835. DeleteServiceAndGroups(
  3836. IN HINSTANCE hInstance,
  3837. IN BOOL fUnattended,
  3838. IN HWND hwnd)
  3839. {
  3840. SC_HANDLE hSCManager = NULL;
  3841. SC_HANDLE hSC = NULL;
  3842. HRESULT hr;
  3843. hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  3844. if (NULL == hSCManager)
  3845. {
  3846. hr = myHLastError();
  3847. _JumpError(hr, error, "OpenSCManager");
  3848. }
  3849. hSC = OpenService(hSCManager, wszSERVICE_NAME, SERVICE_ALL_ACCESS);
  3850. if (NULL != hSC)
  3851. {
  3852. if (!DeleteService(hSC))
  3853. {
  3854. hr = myHLastError();
  3855. CertErrorMessageBox(
  3856. hInstance,
  3857. fUnattended,
  3858. hwnd,
  3859. IDS_ERR_DELETESERVICE,
  3860. hr,
  3861. wszSERVICE_NAME);
  3862. _PrintError(hr, "DeleteService");
  3863. }
  3864. CloseServiceHandle(hSC);
  3865. }
  3866. error:
  3867. if (NULL != hSCManager)
  3868. {
  3869. CloseServiceHandle(hSCManager);
  3870. }
  3871. }
  3872. HRESULT SetCertSrvInstallVersion()
  3873. {
  3874. HRESULT hr;
  3875. hr = mySetCertRegDWValueEx(
  3876. FALSE,
  3877. NULL,
  3878. NULL,
  3879. NULL,
  3880. wszREGVERSION,
  3881. (CSVER_MAJOR << 16) | CSVER_MINOR);
  3882. _PrintIfErrorStr(hr, "mySetCertRegDWValueEx", wszREGVERSION);
  3883. return hr;
  3884. }
  3885. HRESULT
  3886. CreateWebClientRegEntries(
  3887. BOOL fUpgrade,
  3888. PER_COMPONENT_DATA *pComp)
  3889. {
  3890. HRESULT hr;
  3891. CAWEBCLIENTSETUPINFO *pClient = pComp->CA.pClient;
  3892. hr = mySetCertRegStrValueEx(fUpgrade, NULL, NULL, NULL,
  3893. wszREGWEBCLIENTCAMACHINE, pClient->pwszWebCAMachine);
  3894. _JumpIfError(hr, error, "mySetCertRegStrValueEx");
  3895. hr = mySetCertRegStrValueEx(fUpgrade, NULL, NULL, NULL,
  3896. wszREGWEBCLIENTCANAME, pClient->pwszWebCAName);
  3897. _JumpIfError(hr, error, "mySetCertRegStrValueEx");
  3898. hr = mySetCertRegDWValueEx(fUpgrade, NULL, NULL, NULL,
  3899. wszREGWEBCLIENTCATYPE, pClient->WebCAType);
  3900. _JumpIfError(hr, error, "mySetCertRegDWValueEx");
  3901. hr = SetCertSrvInstallVersion();
  3902. _JumpIfError(hr, error, "SetCertSrvInstallVersion");
  3903. if (NULL != pClient->pwszSharedFolder)
  3904. {
  3905. hr = mySetCertRegStrValueEx(fUpgrade, NULL, NULL, NULL,
  3906. wszREGDIRECTORY, pClient->pwszSharedFolder);
  3907. _JumpIfError(hr, error, "mySetCertRegStrValue");
  3908. }
  3909. hr = S_OK;
  3910. error:
  3911. CSILOG(hr, IDS_LOG_CREATE_CLIENT_REG, NULL, NULL, NULL);
  3912. return hr;
  3913. }
  3914. HRESULT
  3915. UpgradeWebClientRegEntries(
  3916. PER_COMPONENT_DATA *pComp)
  3917. {
  3918. HRESULT hr;
  3919. hr = CreateWebClientRegEntries(TRUE, pComp);
  3920. _JumpIfError(hr, error, "CreateWebClientRegEntries");
  3921. // hr = S_OK;
  3922. error:
  3923. return hr;
  3924. }
  3925. HRESULT
  3926. UninstallCore(
  3927. IN HWND hwnd,
  3928. IN PER_COMPONENT_DATA *pComp,
  3929. IN DWORD PerCentCompleteBase,
  3930. IN DWORD PerCentCompleteMax,
  3931. IN BOOL fPreserveClient,
  3932. IN BOOL fRemoveVD,
  3933. IN BOOL fPreserveToDoList)
  3934. {
  3935. BOOL fCoInit = FALSE;
  3936. HRESULT hr;
  3937. WCHAR *pwszSharedFolder = NULL;
  3938. WCHAR *pwszSanitizedCAName = NULL;
  3939. ENUM_CATYPES caType = ENUM_UNKNOWN_CA;
  3940. BOOL fUseDS = FALSE;
  3941. WCHAR *pwszDBDirectory = NULL;
  3942. WCHAR *pwszLogDirectory = NULL;
  3943. WCHAR *pwszSysDirectory = NULL;
  3944. WCHAR *pwszTmpDirectory = NULL;
  3945. DWORD DBSessionCount = 0;
  3946. DWORD PerCentCompleteDelta;
  3947. PerCentCompleteDelta = (PerCentCompleteMax - PerCentCompleteBase) / 10;
  3948. #define _UNINSTALLPERCENT(tenths) \
  3949. (PerCentCompleteBase + (tenths) * PerCentCompleteDelta)
  3950. // get current active CA info
  3951. hr = myGetCertRegStrValue(NULL, NULL, NULL, wszREGACTIVE, &pwszSanitizedCAName);
  3952. _PrintIfError(hr, "UninstallCore(no active CA)");
  3953. if (S_OK == hr)
  3954. {
  3955. hr = ArchiveCACertificate(pwszSanitizedCAName);
  3956. _PrintIfError2(hr, "ArchiveCACertificate", HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  3957. hr = myGetCertRegDWValue(pwszSanitizedCAName, NULL, NULL, wszREGCATYPE, (DWORD*)&caType);
  3958. _PrintIfError(hr, "no reg ca type");
  3959. hr = myGetCertRegDWValue(pwszSanitizedCAName, NULL, NULL, wszREGCAUSEDS, (DWORD*)&fUseDS);
  3960. _PrintIfError(hr, "no reg use ds");
  3961. hr = DeleteCertificates(pwszSanitizedCAName, IsRootCA(caType));
  3962. if(S_OK != hr)
  3963. {
  3964. CertWarningMessageBox(
  3965. pComp->hInstance,
  3966. pComp->fUnattended,
  3967. hwnd,
  3968. IDS_IDINFO_DELETECERTIFICATES,
  3969. 0,
  3970. NULL);
  3971. }
  3972. }
  3973. hr = myGetCertRegStrValue(NULL, NULL, NULL, wszREGDIRECTORY, &pwszSharedFolder);
  3974. _PrintIfError(hr, "no shared folder");
  3975. hr = myGetCertRegStrValue(NULL, NULL, NULL, wszREGDBDIRECTORY, &pwszDBDirectory);
  3976. _PrintIfError(hr, "no db directory");
  3977. hr = myGetCertRegStrValue(NULL, NULL, NULL, wszREGDBLOGDIRECTORY, &pwszLogDirectory);
  3978. _PrintIfError(hr, "no log directory");
  3979. hr = myGetCertRegStrValue(NULL, NULL, NULL, wszREGDBSYSDIRECTORY, &pwszSysDirectory);
  3980. _PrintIfError(hr, "no sys directory");
  3981. hr = myGetCertRegStrValue(NULL, NULL, NULL, wszREGDBTEMPDIRECTORY, &pwszTmpDirectory);
  3982. _PrintIfError(hr, "no tmp directory");
  3983. hr = myGetCertRegDWValue(NULL, NULL, NULL, wszREGDBSESSIONCOUNT, &DBSessionCount);
  3984. _PrintIfError(hr, "no session count");
  3985. hr = CoInitialize(NULL);
  3986. if (S_OK != hr && S_FALSE != hr)
  3987. {
  3988. _JumpError(hr, error, "CoInitialize");
  3989. }
  3990. fCoInit = TRUE;
  3991. DeleteServiceAndGroups(pComp->hInstance, pComp->fUnattended, hwnd);
  3992. certocmBumpGasGauge(pComp, _UNINSTALLPERCENT(1) DBGPARM(L"UninstallCore"));
  3993. if (!fPreserveToDoList)
  3994. {
  3995. // if we're uninstalling, always clear post-base ToDo list
  3996. RegDeleteKey(HKEY_LOCAL_MACHINE, wszREGKEYCERTSRVTODOLIST);
  3997. }
  3998. if (fPreserveClient)
  3999. {
  4000. hr = RegisterAndUnRegisterDLLs(RD_CLIENT, pComp, hwnd);
  4001. _JumpIfError(hr, error, "RegisterAndUnRegisterDLLs");
  4002. hr = CreateCertWebIncPages(hwnd, pComp, FALSE /*IsServer*/, FALSE);
  4003. _JumpIfError(hr, error, "CreateCertWebIncPages");
  4004. }
  4005. certocmBumpGasGauge(pComp, _UNINSTALLPERCENT(2) DBGPARM(L"UninstallCore"));
  4006. DeleteProgramGroups(TRUE, pComp);
  4007. if (fPreserveClient)
  4008. {
  4009. hr = CreateProgramGroups(TRUE, pComp, hwnd);
  4010. _JumpIfError(hr, error, "CreateProgramGroups");
  4011. }
  4012. certocmBumpGasGauge(pComp, _UNINSTALLPERCENT(3) DBGPARM(L"UninstallCore"));
  4013. UnregisterDcomServer(
  4014. CLSID_CCertRequestD,
  4015. wszREQUESTVERINDPROGID,
  4016. wszREQUESTPROGID);
  4017. certocmBumpGasGauge(pComp, _UNINSTALLPERCENT(4) DBGPARM(L"UninstallCore"));
  4018. UnregisterDcomServer(
  4019. CLSID_CCertAdminD,
  4020. wszADMINVERINDPROGID,
  4021. wszADMINPROGID);
  4022. certocmBumpGasGauge(pComp, _UNINSTALLPERCENT(5) DBGPARM(L"UninstallCore"));
  4023. UnregisterDcomApp();
  4024. certocmBumpGasGauge(pComp, _UNINSTALLPERCENT(6) DBGPARM(L"UninstallCore"));
  4025. if (fRemoveVD && !fPreserveClient)
  4026. {
  4027. DisableVRootsAndShares(TRUE, TRUE);
  4028. myDeleteFilePattern(pComp->pwszSystem32, wszCERTSRV, TRUE);
  4029. }
  4030. certocmBumpGasGauge(pComp, _UNINSTALLPERCENT(7) DBGPARM(L"UninstallCore"));
  4031. if (NULL != pwszSharedFolder)
  4032. {
  4033. // this must be restore before CreateConfigFiles()
  4034. hr = mySetCertRegStrValue(NULL, NULL, NULL,
  4035. wszREGDIRECTORY, pwszSharedFolder);
  4036. _PrintIfError(hr, "mySetCertRegStrValue");
  4037. //remove entry
  4038. hr = CreateConfigFiles(pwszSharedFolder, pComp, TRUE, hwnd);
  4039. _PrintIfError2(hr, "CreateConfigFiles(Remove old entry)", hr);
  4040. }
  4041. certocmBumpGasGauge(pComp, _UNINSTALLPERCENT(8) DBGPARM(L"UninstallCore"));
  4042. // restore db path
  4043. if (NULL != pwszDBDirectory)
  4044. {
  4045. hr = mySetCertRegStrValue(NULL, NULL, NULL,
  4046. wszREGDBDIRECTORY, pwszDBDirectory);
  4047. _PrintIfError(hr, "mySetCertRegStrValue");
  4048. }
  4049. if (NULL != pwszLogDirectory)
  4050. {
  4051. hr = mySetCertRegStrValue(NULL, NULL, NULL,
  4052. wszREGDBLOGDIRECTORY, pwszLogDirectory);
  4053. _PrintIfError(hr, "mySetCertRegStrValue");
  4054. }
  4055. if (NULL != pwszSysDirectory)
  4056. {
  4057. hr = mySetCertRegStrValue(NULL, NULL, NULL,
  4058. wszREGDBSYSDIRECTORY, pwszSysDirectory);
  4059. _PrintIfError(hr, "mySetCertRegStrValue");
  4060. }
  4061. if (NULL != pwszTmpDirectory)
  4062. {
  4063. hr = mySetCertRegStrValue(NULL, NULL, NULL,
  4064. wszREGDBTEMPDIRECTORY, pwszTmpDirectory);
  4065. _PrintIfError(hr, "mySetCertRegStrValue");
  4066. }
  4067. if (0 != DBSessionCount)
  4068. {
  4069. hr = mySetCertRegDWValue(NULL, NULL, NULL,
  4070. wszREGDBSESSIONCOUNT, DBSessionCount);
  4071. _PrintIfError(hr, "mySetCertRegDWValueEx");
  4072. }
  4073. if (fPreserveClient)
  4074. {
  4075. // this means uninstall server component and keep web client
  4076. hr = CreateWebClientRegEntries(FALSE, pComp);
  4077. _JumpIfError(hr, error, "CreateWebClientRegEntries");
  4078. }
  4079. DeleteObsoleteResidue();
  4080. DeleteOldFilesAndDirectories(pComp);
  4081. certocmBumpGasGauge(pComp, _UNINSTALLPERCENT(9) DBGPARM(L"UninstallCore"));
  4082. if (fUseDS)
  4083. {
  4084. hr = RemoveCAInDS(pwszSanitizedCAName);
  4085. _PrintIfError2(hr, "RemoveCAInDS", hr);
  4086. }
  4087. certocmBumpGasGauge(pComp, PerCentCompleteMax DBGPARM(L"UninstallCore"));
  4088. hr = S_OK;
  4089. error:
  4090. if (NULL != pwszSanitizedCAName)
  4091. {
  4092. LocalFree(pwszSanitizedCAName);
  4093. }
  4094. if (NULL != pwszSharedFolder)
  4095. {
  4096. LocalFree(pwszSharedFolder);
  4097. }
  4098. if (NULL != pwszDBDirectory)
  4099. {
  4100. LocalFree(pwszDBDirectory);
  4101. }
  4102. if (NULL != pwszLogDirectory)
  4103. {
  4104. LocalFree(pwszLogDirectory);
  4105. }
  4106. if (NULL != pwszSysDirectory)
  4107. {
  4108. LocalFree(pwszSysDirectory);
  4109. }
  4110. if (NULL != pwszTmpDirectory)
  4111. {
  4112. LocalFree(pwszTmpDirectory);
  4113. }
  4114. if (fCoInit)
  4115. {
  4116. CoUninitialize();
  4117. }
  4118. return(hr);
  4119. }
  4120. HRESULT
  4121. AddCAToRPCNullSessions()
  4122. {
  4123. HRESULT hr;
  4124. HKEY hRegKey = NULL;
  4125. char *pszOriginal = NULL;
  4126. char *psz;
  4127. DWORD cb;
  4128. DWORD cbTmp;
  4129. DWORD cbSum;
  4130. DWORD dwType;
  4131. hr = RegOpenKeyExA(
  4132. HKEY_LOCAL_MACHINE,
  4133. szNULL_SESSION_REG_LOCATION,
  4134. 0, // dwOptions
  4135. KEY_READ | KEY_WRITE,
  4136. &hRegKey);
  4137. _JumpIfError(hr, error, "RegOpenKeyExA");
  4138. // Need to get the size of the value first
  4139. hr = RegQueryValueExA(hRegKey, szNULL_SESSION_VALUE, 0, &dwType, NULL, &cb);
  4140. _JumpIfError(hr, error, "RegQueryValueExA");
  4141. if (REG_MULTI_SZ != dwType)
  4142. {
  4143. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  4144. _JumpError(hr, error, "RegQueryValueExA: Type");
  4145. }
  4146. cb += sizeof(rgcCERT_NULL_SESSION) - 1;
  4147. pszOriginal = (char *) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, cb);
  4148. if (NULL == pszOriginal)
  4149. {
  4150. hr = E_OUTOFMEMORY;
  4151. _JumpError(hr, error, "LocalAlloc");
  4152. }
  4153. // get the multi string of RPC null session pipes
  4154. hr = RegQueryValueExA(
  4155. hRegKey,
  4156. szNULL_SESSION_VALUE,
  4157. 0,
  4158. &dwType,
  4159. (BYTE *) pszOriginal,
  4160. &cb);
  4161. _JumpIfError(hr, error, "RegQueryValueExA");
  4162. psz = pszOriginal;
  4163. // look for CERT in the list
  4164. cbSum = 0;
  4165. while (TRUE)
  4166. {
  4167. if (0 == strcmp(rgcCERT_NULL_SESSION, psz))
  4168. {
  4169. break;
  4170. }
  4171. cbTmp = strlen(psz) + 1;
  4172. psz += cbTmp;
  4173. cbSum += cbTmp;
  4174. if (cb < cbSum + 1)
  4175. {
  4176. break;
  4177. }
  4178. if ('\0' == psz[0])
  4179. {
  4180. // add the CA pipe to the multi string
  4181. CopyMemory(psz, rgcCERT_NULL_SESSION, sizeof(rgcCERT_NULL_SESSION));
  4182. // set the new multi string in the reg value
  4183. hr = RegSetValueExA(
  4184. hRegKey,
  4185. szNULL_SESSION_VALUE,
  4186. 0,
  4187. REG_MULTI_SZ,
  4188. (BYTE *) pszOriginal,
  4189. cbSum + sizeof(rgcCERT_NULL_SESSION));
  4190. _JumpIfError(hr, error, "RegSetValueExA");
  4191. break;
  4192. }
  4193. }
  4194. hr = S_OK;
  4195. error:
  4196. if (NULL != pszOriginal)
  4197. {
  4198. LocalFree(pszOriginal);
  4199. }
  4200. if (NULL != hRegKey)
  4201. {
  4202. RegCloseKey(hRegKey);
  4203. }
  4204. return(hr);
  4205. }
  4206. HRESULT
  4207. AddCARegKeyToRegConnectExemptions()
  4208. {
  4209. // add ourselves to list of people that take ACLs seriously
  4210. // and should be allowed to reveal our key to outsiders.
  4211. HRESULT hr;
  4212. LPWSTR pszExempt = NULL;
  4213. HKEY hkeyWinReg = NULL, hkeyAllowedPaths = NULL;
  4214. LPWSTR pszTmp;
  4215. DWORD dwDisposition, dwType;
  4216. DWORD cb=0, cbRegKeyCertSrvPath = (wcslen(wszREGKEYCERTSVCPATH)+1) *sizeof(WCHAR);
  4217. // carefully query this -- if it doesn't exist, we don't have to apply workaround
  4218. hr = RegOpenKeyEx(
  4219. HKEY_LOCAL_MACHINE,
  4220. L"SYSTEM\\CurrentControlSet\\Control\\SecurePipeServers\\Winreg",
  4221. 0,
  4222. KEY_ALL_ACCESS,
  4223. &hkeyWinReg);
  4224. _JumpIfError(hr, Ret, "RegOpenKeyEx");
  4225. // creation of this optional key is always ok if above key exists
  4226. hr = RegCreateKeyEx(
  4227. hkeyWinReg,
  4228. L"AllowedPaths",
  4229. NULL,
  4230. NULL,
  4231. 0,
  4232. KEY_ALL_ACCESS,
  4233. NULL,
  4234. &hkeyAllowedPaths,
  4235. &dwDisposition);
  4236. _JumpIfError(hr, Ret, "RegCreateKeyEx exempt regkey");
  4237. hr = RegQueryValueEx(
  4238. hkeyAllowedPaths,
  4239. L"Machine",
  4240. NULL, // reserved
  4241. &dwType, // type
  4242. NULL, // pb
  4243. &cb);
  4244. _PrintIfError(hr, "RegQueryValueEx exempt regkey 1");
  4245. if ((hr == S_OK) && (dwType != REG_MULTI_SZ))
  4246. {
  4247. hr = HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH);
  4248. _JumpError(hr, Ret, "RegQueryValueEx invalid type");
  4249. }
  4250. // always include at least a terminator
  4251. if (cb < sizeof(WCHAR))
  4252. cb = sizeof(WCHAR);
  4253. pszExempt = (LPWSTR)LocalAlloc(LMEM_FIXED, cb + cbRegKeyCertSrvPath );
  4254. _JumpIfOutOfMemory(hr, Ret, pszExempt);
  4255. // start with double null for safety
  4256. pszExempt[0] = L'\0';
  4257. pszExempt[1] = L'\0';
  4258. hr = RegQueryValueEx(
  4259. hkeyAllowedPaths,
  4260. L"Machine",
  4261. NULL, // reserved
  4262. NULL, // type
  4263. (PBYTE)pszExempt, // pb
  4264. &cb);
  4265. _PrintIfError(hr, "RegQueryValueEx exempt regkey 2");
  4266. pszTmp = pszExempt;
  4267. while(pszTmp[0] != L'\0') // skip all existing strings
  4268. {
  4269. // if entry already exists, bail
  4270. if (0 == lstrcmpi(wszREGKEYCERTSVCPATH, pszTmp))
  4271. {
  4272. hr = S_OK;
  4273. goto Ret;
  4274. }
  4275. pszTmp += wcslen(pszTmp)+1;
  4276. }
  4277. wcscpy(&pszTmp[0], wszREGKEYCERTSVCPATH);
  4278. pszTmp[wcslen(wszREGKEYCERTSVCPATH)+1] = L'\0'; // double NULL
  4279. hr = RegSetValueEx(
  4280. hkeyAllowedPaths,
  4281. L"Machine",
  4282. NULL,
  4283. REG_MULTI_SZ,
  4284. (PBYTE)pszExempt,
  4285. cb + cbRegKeyCertSrvPath);
  4286. _JumpIfError(hr, Ret, "RegSetValueEx exempt regkey");
  4287. Ret:
  4288. if (hkeyAllowedPaths)
  4289. RegCloseKey(hkeyAllowedPaths);
  4290. if (hkeyWinReg)
  4291. RegCloseKey(hkeyWinReg);
  4292. if (pszExempt)
  4293. LocalFree(pszExempt);
  4294. return hr;
  4295. }
  4296. HRESULT
  4297. helperGetFilesNotToRestore(
  4298. PER_COMPONENT_DATA *pComp,
  4299. OUT WCHAR **ppwszz)
  4300. {
  4301. HRESULT hr;
  4302. WCHAR *pwsz;
  4303. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  4304. DWORD cwc;
  4305. WCHAR const wszDBDIRPATTERN[] = L"\\*.edb";
  4306. WCHAR const wszDBLOGDIRPATTERN[] = L"\\*";
  4307. *ppwszz = NULL;
  4308. cwc = wcslen(pServer->pwszDBDirectory) +
  4309. WSZARRAYSIZE(wszDBDIRPATTERN) +
  4310. 1 +
  4311. wcslen(pServer->pwszLogDirectory) +
  4312. WSZARRAYSIZE(wszDBLOGDIRPATTERN) +
  4313. 1 +
  4314. 1;
  4315. pwsz = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
  4316. _JumpIfOutOfMemory(hr, error, pwsz);
  4317. *ppwszz = pwsz;
  4318. wcscpy(pwsz, pServer->pwszDBDirectory);
  4319. wcscat(pwsz, wszDBDIRPATTERN);
  4320. pwsz += wcslen(pwsz) + 1;
  4321. wcscpy(pwsz, pServer->pwszLogDirectory);
  4322. wcscat(pwsz, wszDBLOGDIRPATTERN);
  4323. pwsz += wcslen(pwsz) + 1;
  4324. *pwsz = L'\0';
  4325. CSASSERT(cwc == (DWORD) (pwsz - *ppwszz + 1));
  4326. hr = S_OK;
  4327. error:
  4328. return(hr);
  4329. }
  4330. HRESULT
  4331. CreateServerRegEntries(
  4332. HWND hwnd,
  4333. BOOL fUpgrade,
  4334. PER_COMPONENT_DATA *pComp)
  4335. {
  4336. HRESULT hr;
  4337. HKEY hKeyBase = NULL;
  4338. WCHAR *pwszCLSIDCertGetConfig = NULL;
  4339. WCHAR *pwszCLSIDCertRequest = NULL;
  4340. WCHAR *pwszCRLPeriod = NULL;
  4341. WCHAR *pwszCRLDeltaPeriod = NULL;
  4342. WCHAR *pwszzCRLPublicationValue = NULL;
  4343. WCHAR *pwszzCACertPublicationValue = NULL;
  4344. WCHAR *pwszzRequestExtensionList = NULL;
  4345. WCHAR *pwszzDisableExtensionList = NULL;
  4346. WCHAR *pwszzFilesNotToRestore = NULL;
  4347. WCHAR *pwszProvNameReg = NULL;
  4348. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  4349. DWORD dwUpgradeFlags = fUpgrade ? CSREG_UPGRADE : 0x0;
  4350. DWORD dwAppendFlags = 0x0; // default
  4351. DWORD dwCRLPeriodCount, dwCRLDeltaPeriodCount;
  4352. LDAP *pld = NULL;
  4353. BSTR strDomainDN = NULL;
  4354. BSTR strConfigDN = NULL;
  4355. // no error checking?
  4356. hr = AddCAToRPCNullSessions();
  4357. _PrintIfError(hr, "AddCAToRPCNullSessions");
  4358. hr = AddCARegKeyToRegConnectExemptions();
  4359. _PrintIfError(hr, "AddCARegKeyToRegConnectExemptions");
  4360. // create the CA key, so we can set security on it.
  4361. hr = myCreateCertRegKey(pServer->pwszSanitizedName, NULL, NULL);
  4362. _JumpIfError(hr, error, "myCreateCertRegKey");
  4363. // configuration level
  4364. // active ca
  4365. hr = mySetCertRegStrValueEx(
  4366. fUpgrade,
  4367. NULL,
  4368. NULL,
  4369. NULL,
  4370. wszREGACTIVE,
  4371. pServer->pwszSanitizedName);
  4372. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGACTIVE);
  4373. if (NULL != pServer->pwszSharedFolder)
  4374. {
  4375. // shared folder
  4376. hr = mySetCertRegStrValueEx(
  4377. fUpgrade,
  4378. NULL,
  4379. NULL,
  4380. NULL,
  4381. wszREGDIRECTORY,
  4382. pServer->pwszSharedFolder);
  4383. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGDIRECTORY);
  4384. }
  4385. // db dir
  4386. hr = mySetCertRegStrValueEx(
  4387. fUpgrade,
  4388. NULL,
  4389. NULL,
  4390. NULL,
  4391. wszREGDBDIRECTORY,
  4392. pServer->pwszDBDirectory);
  4393. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGDBDIRECTORY);
  4394. // log dir
  4395. hr = mySetCertRegStrValueEx(
  4396. fUpgrade,
  4397. NULL,
  4398. NULL,
  4399. NULL,
  4400. wszREGDBLOGDIRECTORY,
  4401. pServer->pwszLogDirectory);
  4402. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGDBLOGDIRECTORY);
  4403. // db tmp dir
  4404. hr = mySetCertRegStrValueEx(
  4405. fUpgrade,
  4406. NULL,
  4407. NULL,
  4408. NULL,
  4409. wszREGDBTEMPDIRECTORY,
  4410. pServer->pwszLogDirectory);
  4411. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGDBTEMPDIRECTORY);
  4412. // db sys dir
  4413. hr = mySetCertRegStrValueEx(
  4414. fUpgrade,
  4415. NULL,
  4416. NULL,
  4417. NULL,
  4418. wszREGDBSYSDIRECTORY,
  4419. pServer->pwszLogDirectory);
  4420. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGDBSYSDIRECTORY);
  4421. hr = mySetCertRegDWValueEx(
  4422. fUpgrade,
  4423. NULL,
  4424. NULL,
  4425. NULL,
  4426. wszREGDBSESSIONCOUNT,
  4427. DBSESSIONCOUNTDEFAULT);
  4428. _JumpIfErrorStr(hr, error, "mySetCertRegDWValueEx", wszREGDBSESSIONCOUNT);
  4429. hr = SetCertSrvInstallVersion();
  4430. _JumpIfError(hr, error, "SetCertSrvInstallVersion");
  4431. if (!fUpgrade)
  4432. {
  4433. // preserve db
  4434. hr = SetSetupStatus(NULL, SETUP_CREATEDB_FLAG, !pServer->fPreserveDB);
  4435. _JumpIfError(hr, error, "SetSetupStatus");
  4436. }
  4437. // ca level
  4438. if (!fUpgrade && pServer->fUseDS)
  4439. {
  4440. hr = myLdapOpen(&pld, &strDomainDN, &strConfigDN);
  4441. _JumpIfError(hr, error, "myLdapOpen");
  4442. // Config DN
  4443. hr = mySetCertRegStrValueEx(
  4444. FALSE,
  4445. pServer->pwszSanitizedName,
  4446. NULL,
  4447. NULL,
  4448. wszREGDSCONFIGDN,
  4449. strConfigDN);
  4450. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGDSCONFIGDN);
  4451. // Domain DN
  4452. hr = mySetCertRegStrValueEx(
  4453. FALSE,
  4454. pServer->pwszSanitizedName,
  4455. NULL,
  4456. NULL,
  4457. wszREGDSDOMAINDN,
  4458. strDomainDN);
  4459. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGDSDOMAINDN);
  4460. }
  4461. // ca type
  4462. CSASSERT(IsEnterpriseCA(pServer->CAType) || IsStandaloneCA(pServer->CAType));
  4463. hr = mySetCertRegDWValueEx(
  4464. fUpgrade,
  4465. pServer->pwszSanitizedName,
  4466. NULL,
  4467. NULL,
  4468. wszREGCATYPE,
  4469. pServer->CAType);
  4470. _JumpIfErrorStr(hr, error, "mySetCertRegDWValueEx", wszREGCATYPE);
  4471. // use DS flag
  4472. hr = mySetCertRegDWValueEx(
  4473. fUpgrade,
  4474. pServer->pwszSanitizedName,
  4475. NULL,
  4476. NULL,
  4477. wszREGCAUSEDS,
  4478. pServer->fUseDS);
  4479. _JumpIfErrorStr(hr, error, "mySetCertRegDWValueEx", wszREGCAUSEDS);
  4480. // teletex flag
  4481. hr = mySetCertRegDWValueEx(
  4482. fUpgrade,
  4483. pServer->pwszSanitizedName,
  4484. NULL,
  4485. NULL,
  4486. wszREGFORCETELETEX,
  4487. ENUM_TELETEX_AUTO | ENUM_TELETEX_UTF8);
  4488. _JumpIfErrorStr(hr, error, "mySetCertRegDWValueEx", wszREGFORCETELETEX);
  4489. hr = mySetCertRegMultiStrValueEx(
  4490. dwUpgradeFlags,
  4491. pServer->pwszSanitizedName,
  4492. NULL,
  4493. NULL,
  4494. wszSECUREDATTRIBUTES,
  4495. wszzDEFAULTSIGNEDATTRIBUTES);
  4496. _JumpIfErrorStr(hr, error, "mySetCertRegMultiStrValueEx", wszSECUREDATTRIBUTES,);
  4497. // common name
  4498. hr = mySetCertRegStrValueEx(
  4499. fUpgrade,
  4500. pServer->pwszSanitizedName,
  4501. NULL,
  4502. NULL,
  4503. wszREGCOMMONNAME,
  4504. pServer->pwszCACommonName);
  4505. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGCOMMONNAME);
  4506. // enable reg
  4507. hr = mySetCertRegDWValueEx(
  4508. fUpgrade,
  4509. pServer->pwszSanitizedName,
  4510. NULL,
  4511. NULL,
  4512. wszREGENABLED,
  4513. TRUE);
  4514. _JumpIfErrorStr(hr, error, "mySetCertRegDWValueEx", wszREGENABLED);
  4515. // policy flag
  4516. hr = mySetCertRegDWValueEx(
  4517. fUpgrade,
  4518. pServer->pwszSanitizedName,
  4519. NULL,
  4520. NULL,
  4521. wszREGPOLICYFLAGS,
  4522. 0);
  4523. _JumpIfErrorStr(hr, error, "mySetCertRegDWValueEx", wszREGPOLICYFLAGS);
  4524. // enroll compatible flag, always turn it off
  4525. // BUG, consider use mySetCertRegDWValueEx with fUpgrade
  4526. // after W2K to support CertEnrollCompatible upgrade
  4527. hr = mySetCertRegDWValue(
  4528. pServer->pwszSanitizedName,
  4529. NULL,
  4530. NULL,
  4531. wszREGCERTENROLLCOMPATIBLE,
  4532. FALSE);
  4533. _JumpIfErrorStr(hr, error, "mySetCertRegDWValue", wszREGCERTENROLLCOMPATIBLE);
  4534. // Cert Server CRL Edit Flags
  4535. hr = mySetCertRegDWValueEx(
  4536. fUpgrade,
  4537. pServer->pwszSanitizedName,
  4538. NULL,
  4539. NULL,
  4540. wszREGCRLEDITFLAGS,
  4541. EDITF_ENABLEAKIKEYID);
  4542. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGCRLEDITFLAGS);
  4543. // Cert Server CRL Flags
  4544. hr = mySetCertRegDWValueEx(
  4545. fUpgrade,
  4546. pServer->pwszSanitizedName,
  4547. NULL,
  4548. NULL,
  4549. wszREGCRLFLAGS,
  4550. CRLF_DELETE_EXPIRED_CRLS);
  4551. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGCRLFLAGS);
  4552. hr = mySetCertRegDWValueEx(
  4553. fUpgrade,
  4554. pServer->pwszSanitizedName,
  4555. NULL,
  4556. NULL,
  4557. wszREGENFORCEX500NAMELENGTHS,
  4558. TRUE);
  4559. _JumpIfErrorStr(hr, error, "mySetCertRegDWValueEx", wszREGENFORCEX500NAMELENGTHS);
  4560. // subject template
  4561. hr = mySetCertRegMultiStrValueEx(
  4562. 0, // dwUpgradeFlags: always overwrite!
  4563. pServer->pwszSanitizedName,
  4564. NULL,
  4565. NULL,
  4566. wszREGSUBJECTTEMPLATE,
  4567. wszzREGSUBJECTTEMPLATEVALUE);
  4568. _JumpIfErrorStr(hr, error, "mySetCertRegMultiStrValueEx", wszREGSUBJECTTEMPLATE);
  4569. // (hard code) clock skew minutes
  4570. hr = mySetCertRegDWValueEx(
  4571. fUpgrade,
  4572. pServer->pwszSanitizedName,
  4573. NULL,
  4574. NULL,
  4575. wszREGCLOCKSKEWMINUTES,
  4576. CCLOCKSKEWMINUTESDEFAULT);
  4577. _JumpIfErrorStr(hr, error, "mySetCertRegDWValueEx", wszREGCLOCKSKEWMINUTES);
  4578. // (hard code) log level
  4579. hr = mySetCertRegDWValueEx(
  4580. fUpgrade,
  4581. pServer->pwszSanitizedName,
  4582. NULL,
  4583. NULL,
  4584. wszREGLOGLEVEL,
  4585. CERTLOG_WARNING);
  4586. _JumpIfErrorStr(hr, error, "mySetCertRegDWValueEx", wszREGLOGLEVEL);
  4587. hr = mySetCertRegDWValueEx(
  4588. fUpgrade,
  4589. pServer->pwszSanitizedName,
  4590. NULL,
  4591. NULL,
  4592. wszREGHIGHSERIAL,
  4593. 0);
  4594. _JumpIfErrorStr(hr, error, "mySetCertRegDWValueEx", wszREGLOGLEVEL);
  4595. // register server name
  4596. hr = mySetCertRegStrValueEx(
  4597. fUpgrade,
  4598. pServer->pwszSanitizedName,
  4599. NULL,
  4600. NULL,
  4601. wszREGCASERVERNAME,
  4602. pComp->pwszServerName);
  4603. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGCASERVERNAME);
  4604. // default validity period string and count for issued certs
  4605. // use years for string
  4606. hr = mySetCertRegStrValueEx(
  4607. fUpgrade,
  4608. pServer->pwszSanitizedName,
  4609. NULL,
  4610. NULL,
  4611. wszREGVALIDITYPERIODSTRING,
  4612. wszVALIDITYPERIODSTRINGDEFAULT);
  4613. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGVALIDITYPERIODSTRING);
  4614. // validity period count
  4615. // use 1 year for standalone and 2 years for enterprise
  4616. hr = mySetCertRegDWValueEx(
  4617. fUpgrade,
  4618. pServer->pwszSanitizedName,
  4619. NULL,
  4620. NULL,
  4621. wszREGVALIDITYPERIODCOUNT,
  4622. IsEnterpriseCA(pServer->CAType)?
  4623. dwVALIDITYPERIODCOUNTDEFAULT_ENTERPRISE :
  4624. dwVALIDITYPERIODCOUNTDEFAULT_STANDALONE);
  4625. _JumpIfErrorStr(hr, error, "mySetCertRegDWValueEx", wszREGVALIDITYPERIODCOUNT);
  4626. hr = mySetCertRegMultiStrValueEx(
  4627. dwUpgradeFlags,
  4628. pServer->pwszSanitizedName,
  4629. NULL,
  4630. NULL,
  4631. wszREGCAXCHGCERTHASH,
  4632. NULL);
  4633. _JumpIfErrorStr(hr, error, "mySetCertRegMultiStrValueEx", wszREGCAXCHGCERTHASH);
  4634. hr = mySetCertRegMultiStrValueEx(
  4635. dwUpgradeFlags,
  4636. pServer->pwszSanitizedName,
  4637. NULL,
  4638. NULL,
  4639. wszREGKRACERTHASH,
  4640. NULL);
  4641. _JumpIfErrorStr(hr, error, "mySetCertRegMultiStrValueEx", wszREGKRACERTHASH);
  4642. hr = mySetCertRegDWValueEx(
  4643. dwUpgradeFlags,
  4644. pServer->pwszSanitizedName,
  4645. NULL,
  4646. NULL,
  4647. wszREGKRACERTCOUNT,
  4648. 0);
  4649. _JumpIfErrorStr(hr, error, "mySetCertRegDWValueEx", wszREGKRACERTCOUNT);
  4650. hr = mySetCertRegDWValueEx(
  4651. dwUpgradeFlags,
  4652. pServer->pwszSanitizedName,
  4653. NULL,
  4654. NULL,
  4655. wszREGKRAFLAGS,
  4656. 0);
  4657. _JumpIfErrorStr(hr, error, "mySetCertRegDWValueEx", wszREGKRAFLAGS);
  4658. // CRL Publication URLs:
  4659. hr = csiGetCRLPublicationURLTemplates(
  4660. pServer->fUseDS,
  4661. pComp->pwszSystem32,
  4662. &pwszzCRLPublicationValue);
  4663. _JumpIfError(hr, error, "csiGetCRLPublicationURLTemplates");
  4664. hr = mySetCertRegMultiStrValueEx(
  4665. dwUpgradeFlags | CSREG_MERGE,
  4666. pServer->pwszSanitizedName,
  4667. NULL,
  4668. NULL,
  4669. wszREGCRLPUBLICATIONURLS,
  4670. pwszzCRLPublicationValue);
  4671. _JumpIfErrorStr(hr, error, "mySetCertRegMultiStrValueEx", wszREGCRLPUBLICATIONURLS);
  4672. // if this API returns non-null strings, it's got good data
  4673. hr = csiGetCRLPublicationParams(
  4674. TRUE,
  4675. &pwszCRLPeriod,
  4676. &dwCRLPeriodCount);
  4677. _PrintIfError(hr, "csiGetCRLPublicationParams");
  4678. // crl period string
  4679. hr = mySetCertRegStrValueEx(
  4680. fUpgrade,
  4681. pServer->pwszSanitizedName,
  4682. NULL,
  4683. NULL,
  4684. wszREGCRLPERIODSTRING,
  4685. (pwszCRLPeriod == NULL) ? wszCRLPERIODSTRINGDEFAULT : pwszCRLPeriod);
  4686. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGCRLPERIODSTRING);
  4687. // crl period count
  4688. hr = mySetCertRegDWValueEx(
  4689. fUpgrade,
  4690. pServer->pwszSanitizedName,
  4691. NULL,
  4692. NULL,
  4693. wszREGCRLPERIODCOUNT,
  4694. (pwszCRLPeriod == NULL) ? dwCRLPERIODCOUNTDEFAULT : dwCRLPeriodCount);
  4695. _JumpIfErrorStr(hr, error, "mySetCertRegDWValueEx", wszREGCRLPERIODCOUNT);
  4696. // crl overlap period string
  4697. hr = mySetCertRegStrValueEx(
  4698. fUpgrade,
  4699. pServer->pwszSanitizedName,
  4700. NULL,
  4701. NULL,
  4702. wszREGCRLOVERLAPPERIODSTRING,
  4703. wszCRLOVERLAPPERIODSTRINGDEFAULT);
  4704. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGCRLOVERLAPPERIODSTRING);
  4705. // crl overlap period count
  4706. hr = mySetCertRegDWValueEx(
  4707. fUpgrade,
  4708. pServer->pwszSanitizedName,
  4709. NULL,
  4710. NULL,
  4711. wszREGCRLOVERLAPPERIODCOUNT,
  4712. dwCRLOVERLAPPERIODCOUNTDEFAULT);
  4713. _JumpIfErrorStr(hr, error, "mySetCertRegDWValueEx", wszREGCRLOVERLAPPERIODCOUNT);
  4714. // if this API returns non-null strings, it's got good data
  4715. hr = csiGetCRLPublicationParams(
  4716. FALSE, // delta
  4717. &pwszCRLDeltaPeriod,
  4718. &dwCRLDeltaPeriodCount);
  4719. _PrintIfError(hr, "csiGetCRLPublicationParams");
  4720. // delta crl period string
  4721. hr = mySetCertRegStrValueEx(
  4722. fUpgrade,
  4723. pServer->pwszSanitizedName,
  4724. NULL,
  4725. NULL,
  4726. wszREGCRLDELTAPERIODSTRING,
  4727. (pwszCRLDeltaPeriod == NULL) ? wszCRLDELTAPERIODSTRINGDEFAULT : pwszCRLDeltaPeriod);
  4728. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGCRLDELTAPERIODSTRING);
  4729. // delta crl period count
  4730. hr = mySetCertRegDWValueEx(
  4731. fUpgrade,
  4732. pServer->pwszSanitizedName,
  4733. NULL,
  4734. NULL,
  4735. wszREGCRLDELTAPERIODCOUNT,
  4736. (pwszCRLDeltaPeriod == NULL) ? dwCRLPERIODCOUNTDEFAULT : dwCRLDeltaPeriodCount);
  4737. _JumpIfErrorStr(hr, error, "mySetCertRegDWValueEx", wszREGCRLDELTAPERIODCOUNT);
  4738. // delta crl overlap period string
  4739. hr = mySetCertRegStrValueEx(
  4740. fUpgrade,
  4741. pServer->pwszSanitizedName,
  4742. NULL,
  4743. NULL,
  4744. wszREGCRLDELTAOVERLAPPERIODSTRING,
  4745. wszCRLDELTAOVERLAPPERIODSTRINGDEFAULT);
  4746. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGCRLDELTAOVERLAPPERIODSTRING);
  4747. // delta crl overlap period count
  4748. hr = mySetCertRegDWValueEx(
  4749. fUpgrade,
  4750. pServer->pwszSanitizedName,
  4751. NULL,
  4752. NULL,
  4753. wszREGCRLDELTAOVERLAPPERIODCOUNT,
  4754. dwCRLDELTAOVERLAPPERIODCOUNTDEFAULT);
  4755. _JumpIfErrorStr(hr, error, "mySetCertRegDWValueEx", wszREGCRLDELTAOVERLAPPERIODCOUNT);
  4756. // CA xchg cert validity period string
  4757. hr = mySetCertRegStrValueEx(
  4758. fUpgrade,
  4759. pServer->pwszSanitizedName,
  4760. NULL,
  4761. NULL,
  4762. wszREGCAXCHGVALIDITYPERIODSTRING,
  4763. wszCAXCHGVALIDITYPERIODSTRINGDEFAULT);
  4764. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGCRLDELTAOVERLAPPERIODSTRING);
  4765. // CA xchg cert validity period count
  4766. hr = mySetCertRegDWValueEx(
  4767. fUpgrade,
  4768. pServer->pwszSanitizedName,
  4769. NULL,
  4770. NULL,
  4771. wszREGCAXCHGVALIDITYPERIODCOUNT,
  4772. dwCAXCHGVALIDITYPERIODCOUNTDEFAULT);
  4773. _JumpIfErrorStr(hr, error, "mySetCertRegDWValueEx", wszREGCRLDELTAOVERLAPPERIODCOUNT);
  4774. // CA xchg cert overlap period string
  4775. hr = mySetCertRegStrValueEx(
  4776. fUpgrade,
  4777. pServer->pwszSanitizedName,
  4778. NULL,
  4779. NULL,
  4780. wszREGCAXCHGOVERLAPPERIODSTRING,
  4781. wszCAXCHGOVERLAPPERIODSTRINGDEFAULT);
  4782. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGCRLDELTAOVERLAPPERIODSTRING);
  4783. // CA xchg cert overlap period count
  4784. hr = mySetCertRegDWValueEx(
  4785. fUpgrade,
  4786. pServer->pwszSanitizedName,
  4787. NULL,
  4788. NULL,
  4789. wszREGCAXCHGOVERLAPPERIODCOUNT,
  4790. dwCAXCHGOVERLAPPERIODCOUNTDEFAULT);
  4791. _JumpIfErrorStr(hr, error, "mySetCertRegDWValueEx", wszREGCRLDELTAOVERLAPPERIODCOUNT);
  4792. hr = mySetCertRegDWValueEx(
  4793. fUpgrade,
  4794. pServer->pwszSanitizedName,
  4795. NULL,
  4796. NULL,
  4797. wszREGMAXINCOMINGMESSAGESIZE,
  4798. MAXINCOMINGMESSAGESIZEDEFAULT);
  4799. _JumpIfErrorStr(hr, error, "mySetCertRegDWValueEx", wszREGMAXINCOMINGMESSAGESIZE);
  4800. if (NULL != pServer->pwszSharedFolder)
  4801. {
  4802. // register CA file name for certhier and renewal
  4803. hr = mySetCARegFileNameTemplate(
  4804. wszREGCACERTFILENAME,
  4805. pComp->pwszServerName,
  4806. pServer->pwszSanitizedName,
  4807. pServer->pwszCACertFile);
  4808. _JumpIfError(hr, error, "SetRegCertFileName");
  4809. }
  4810. // policy
  4811. // create default policy entry explicitly to get correct acl if upgrade
  4812. hr = myCreateCertRegKeyEx(
  4813. fUpgrade,
  4814. pServer->pwszSanitizedName,
  4815. wszREGKEYPOLICYMODULES,
  4816. wszCLASS_CERTPOLICY);
  4817. _JumpIfErrorStr(hr, error, "myCreateCertRegKeyEx", wszCLASS_CERTPOLICY);
  4818. // if customized policy, create a new entry with correct acl
  4819. if (fUpgrade &&
  4820. NULL != pServer->pwszCustomPolicy &&
  4821. 0 != wcscmp(wszCLASS_CERTPOLICY, pServer->pwszCustomPolicy) )
  4822. {
  4823. hr = myCreateCertRegKeyEx(
  4824. TRUE, // upgrade
  4825. pServer->pwszSanitizedName,
  4826. wszREGKEYPOLICYMODULES,
  4827. pServer->pwszCustomPolicy);
  4828. _JumpIfError(hr, error, "myCreateCertRegKey");
  4829. }
  4830. // set default policy
  4831. hr = mySetCertRegStrValueEx(
  4832. fUpgrade,
  4833. pServer->pwszSanitizedName,
  4834. wszREGKEYPOLICYMODULES,
  4835. NULL,
  4836. wszREGACTIVE,
  4837. (fUpgrade && (NULL != pServer->pwszCustomPolicy)) ?
  4838. pServer->pwszCustomPolicy :
  4839. wszCLASS_CERTPOLICY);
  4840. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGACTIVE);
  4841. hr = mySetCertRegDWValueEx(
  4842. fUpgrade,
  4843. pServer->pwszSanitizedName,
  4844. wszREGKEYPOLICYMODULES,
  4845. wszCLASS_CERTPOLICY,
  4846. wszREGREVOCATIONTYPE,
  4847. pServer->dwRevocationFlags | pServer->dwUpgradeRevFlags);
  4848. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGREVOCATIONTYPE);
  4849. hr = mySetCertRegDWValueEx(
  4850. fUpgrade,
  4851. pServer->pwszSanitizedName,
  4852. wszREGKEYPOLICYMODULES,
  4853. wszCLASS_CERTPOLICY,
  4854. wszREGCAPATHLENGTH,
  4855. CAPATHLENGTH_INFINITE);
  4856. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGCAPATHLENGTH);
  4857. // revocation url
  4858. hr = mySetCertRegStrValueEx(
  4859. fUpgrade,
  4860. pServer->pwszSanitizedName,
  4861. wszREGKEYPOLICYMODULES,
  4862. wszCLASS_CERTPOLICY,
  4863. wszREGREVOCATIONURL,
  4864. g_wszASPRevocationURLTemplate);
  4865. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGREVOCATIONURL);
  4866. // Exit module publish flags
  4867. hr = mySetCertRegDWValueEx(
  4868. fUpgrade,
  4869. pServer->pwszSanitizedName,
  4870. wszREGKEYEXITMODULES,
  4871. wszCLASS_CERTEXIT,
  4872. wszREGCERTPUBLISHFLAGS,
  4873. pServer->fUseDS ?
  4874. EXITPUB_DEFAULT_ENTERPRISE :
  4875. EXITPUB_DEFAULT_STANDALONE);
  4876. _JumpIfErrorStr(
  4877. hr,
  4878. error,
  4879. "mySetCertRegStrValueEx",
  4880. wszREGCERTPUBLISHFLAGS);
  4881. // Enable Request Extensions:
  4882. hr = helperGetRequestExtensionList(pComp, &pwszzRequestExtensionList);
  4883. _JumpIfError(hr, error, "helperGetRequestExtensionList");
  4884. hr = mySetCertRegMultiStrValueEx(
  4885. dwUpgradeFlags | CSREG_MERGE,
  4886. pServer->pwszSanitizedName,
  4887. wszREGKEYPOLICYMODULES,
  4888. wszCLASS_CERTPOLICY,
  4889. wszREGENABLEREQUESTEXTENSIONLIST,
  4890. pwszzRequestExtensionList);
  4891. _JumpIfErrorStr(hr, error, "mySetCertRegMultiStrValueEx", wszREGENABLEREQUESTEXTENSIONLIST);
  4892. hr = helperGetDisableExtensionList(pComp, &pwszzDisableExtensionList);
  4893. _JumpIfError(hr, error, "helperGetDisableExtensionList");
  4894. // Disables Template Extensions:
  4895. hr = mySetCertRegMultiStrValueEx(
  4896. dwUpgradeFlags | CSREG_MERGE,
  4897. pServer->pwszSanitizedName,
  4898. wszREGKEYPOLICYMODULES,
  4899. wszCLASS_CERTPOLICY,
  4900. wszREGDISABLEEXTENSIONLIST,
  4901. pwszzDisableExtensionList);
  4902. _JumpIfErrorStr(hr, error, "mySetCertRegMultiStrValueEx", wszREGDISABLEEXTENSIONLIST);
  4903. // Subject Alt Name Extension
  4904. hr = mySetCertRegStrValueEx(
  4905. fUpgrade,
  4906. pServer->pwszSanitizedName,
  4907. wszREGKEYPOLICYMODULES,
  4908. wszCLASS_CERTPOLICY,
  4909. wszREGSUBJECTALTNAME,
  4910. wszREGSUBJECTALTNAMEVALUE);
  4911. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGSUBJECTALTNAME);
  4912. // Subject Alt Name 2 Extension
  4913. hr = mySetCertRegStrValueEx(
  4914. fUpgrade,
  4915. pServer->pwszSanitizedName,
  4916. wszREGKEYPOLICYMODULES,
  4917. wszCLASS_CERTPOLICY,
  4918. wszREGSUBJECTALTNAME2,
  4919. wszREGSUBJECTALTNAME2VALUE);
  4920. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGSUBJECTALTNAME2);
  4921. // Request Disposition
  4922. hr = mySetCertRegDWValueEx(
  4923. fUpgrade,
  4924. pServer->pwszSanitizedName,
  4925. wszREGKEYPOLICYMODULES,
  4926. wszCLASS_CERTPOLICY,
  4927. wszREGREQUESTDISPOSITION,
  4928. IsEnterpriseCA(pServer->CAType)?
  4929. REQDISP_DEFAULT_ENTERPRISE :
  4930. REQDISP_DEFAULT_STANDALONE);
  4931. _JumpIfErrorStr(hr, error, "mySetCertRegDWValueEx",
  4932. wszREGREQUESTDISPOSITION);
  4933. // Edit Flags
  4934. hr = mySetCertRegDWValueEx(
  4935. fUpgrade,
  4936. pServer->pwszSanitizedName,
  4937. wszREGKEYPOLICYMODULES,
  4938. wszCLASS_CERTPOLICY,
  4939. wszREGEDITFLAGS,
  4940. IsEnterpriseCA(pServer->CAType)?
  4941. (EDITF_DEFAULT_ENTERPRISE | pServer->dwUpgradeEditFlags) :
  4942. (EDITF_DEFAULT_STANDALONE | pServer->dwUpgradeEditFlags));
  4943. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx", wszREGEDITFLAGS);
  4944. // Issuer Cert URL Flags
  4945. hr = mySetCertRegDWValueEx(
  4946. fUpgrade,
  4947. pServer->pwszSanitizedName,
  4948. wszREGKEYPOLICYMODULES,
  4949. wszCLASS_CERTPOLICY,
  4950. wszREGISSUERCERTURLFLAGS,
  4951. pServer->fUseDS?
  4952. ISSCERT_DEFAULT_DS : ISSCERT_DEFAULT_NODS);
  4953. _JumpIfErrorStr(hr, error, "mySetCertRegStrValueEx",
  4954. wszREGISSUERCERTURLFLAGS);
  4955. hr = mySetCertRegMultiStrValueEx(
  4956. dwUpgradeFlags,
  4957. pServer->pwszSanitizedName,
  4958. wszREGKEYPOLICYMODULES,
  4959. wszCLASS_CERTPOLICY,
  4960. wszREGDEFAULTSMIME,
  4961. wszzREGVALUEDEFAULTSMIME);
  4962. _JumpIfErrorStr(hr, error, "mySetCertRegMultiStrValueEx", wszREGDEFAULTSMIME);
  4963. hr = csiGetCACertPublicationURLTemplates(
  4964. pServer->fUseDS,
  4965. pComp->pwszSystem32,
  4966. &pwszzCACertPublicationValue);
  4967. _JumpIfError(hr, error, "csiGetCACertPublicationURLTemplates");
  4968. hr = mySetCertRegMultiStrValueEx(
  4969. dwUpgradeFlags | CSREG_MERGE,
  4970. pServer->pwszSanitizedName,
  4971. NULL,
  4972. NULL,
  4973. wszREGCACERTPUBLICATIONURLS,
  4974. pwszzCACertPublicationValue);
  4975. _JumpIfErrorStr(hr, error, "mySetCertRegMultiStrValueEx", wszREGCRLPUBLICATIONURLS);
  4976. // exit
  4977. // create default exit entry to get correct acl if upgrade
  4978. hr = myCreateCertRegKeyEx(
  4979. fUpgrade,
  4980. pServer->pwszSanitizedName,
  4981. wszREGKEYEXITMODULES,
  4982. wszCLASS_CERTEXIT);
  4983. _JumpIfErrorStr(hr, error, "myCreateCertRegKeyEx", wszCLASS_CERTPOLICY);
  4984. // if customized exit, create a new entry with correct acl
  4985. if (fUpgrade &&
  4986. NULL != pServer->pwszzCustomExit &&
  4987. 0 != wcscmp(wszCLASS_CERTEXIT, pServer->pwszzCustomExit) )
  4988. {
  4989. // create a new entry for custom exit
  4990. hr = myCreateCertRegKeyEx(
  4991. TRUE, // upgrade
  4992. pServer->pwszSanitizedName,
  4993. wszREGKEYEXITMODULES,
  4994. pServer->pwszzCustomExit);
  4995. _JumpIfError(hr, error, "myCreateCertRegKey");
  4996. }
  4997. // set default exit
  4998. hr = mySetCertRegMultiStrValueEx(
  4999. dwUpgradeFlags,
  5000. pServer->pwszSanitizedName,
  5001. wszREGKEYEXITMODULES,
  5002. NULL,
  5003. wszREGACTIVE,
  5004. (fUpgrade && (NULL != pServer->pwszzCustomExit)) ?
  5005. pServer->pwszzCustomExit :
  5006. wszCLASS_CERTEXIT L"\0");
  5007. _JumpIfErrorStr(hr, error, "mySetCertRegMultiStrValueEx", wszREGACTIVE);
  5008. // set some absolute keys and values
  5009. hr = mySetAbsRegMultiStrValue(
  5010. wszREGKEYKEYSNOTTORESTORE,
  5011. wszREGRESTORECERTIFICATEAUTHORITY,
  5012. wszzREGVALUERESTORECERTIFICATEAUTHORITY);
  5013. _JumpIfError(hr, error, "mySetAbsRegMultiStrValue");
  5014. hr = helperGetFilesNotToRestore(pComp, &pwszzFilesNotToRestore);
  5015. _JumpIfError(hr, error, "helperGetFilesNotToRestore");
  5016. hr = mySetAbsRegMultiStrValue(
  5017. wszREGKEYFILESNOTTOBACKUP,
  5018. wszREGRESTORECERTIFICATEAUTHORITY,
  5019. pwszzFilesNotToRestore);
  5020. _JumpIfError(hr, error, "mySetAbsRegMultiStrValue");
  5021. // ICertGetConfig
  5022. hr = StringFromCLSID(CLSID_CCertGetConfig, &pwszCLSIDCertGetConfig);
  5023. _JumpIfError(hr, error, "StringFromCLSID(CCertGetConfig)");
  5024. hr = mySetAbsRegStrValue(
  5025. wszREGKEYKEYRING,
  5026. wszREGCERTGETCONFIG,
  5027. pwszCLSIDCertGetConfig);
  5028. _JumpIfError(hr, error, "mySetAbsRegStrValue");
  5029. // ICertCertRequest
  5030. hr = StringFromCLSID(CLSID_CCertRequest, &pwszCLSIDCertRequest);
  5031. _JumpIfError(hr, error, "StringFromCLSID(CCertRequest)");
  5032. hr = mySetAbsRegStrValue(
  5033. wszREGKEYKEYRING,
  5034. wszREGCERTREQUEST,
  5035. pwszCLSIDCertRequest);
  5036. _JumpIfError(hr, error, "mySetAbsRegStrValue");
  5037. if (NULL != pServer->pCSPInfo &&
  5038. NULL != pServer->pHashInfo)
  5039. {
  5040. WCHAR const *pwszProvName = pServer->pCSPInfo->pwszProvName;
  5041. DWORD dwProvType;
  5042. ALG_ID idAlg;
  5043. BOOL fMachineKeyset;
  5044. DWORD dwKeySize;
  5045. if (0 == lstrcmpi(pwszProvName, MS_DEF_PROV_W))
  5046. {
  5047. pwszProvName = MS_STRONG_PROV_W;
  5048. }
  5049. hr = SetCertSrvCSP(
  5050. FALSE, // fEncryptionCSP
  5051. pServer->pwszSanitizedName,
  5052. pServer->pCSPInfo->dwProvType,
  5053. pwszProvName,
  5054. pServer->pHashInfo->idAlg,
  5055. pServer->pCSPInfo->fMachineKeyset,
  5056. 0); // dwKeySize
  5057. _JumpIfError(hr, error, "SetCertSrvCSP");
  5058. hr = myGetCertSrvCSP(
  5059. TRUE, // fEncryptionCSP
  5060. pServer->pwszSanitizedName,
  5061. &dwProvType,
  5062. &pwszProvNameReg,
  5063. &idAlg,
  5064. &fMachineKeyset,
  5065. &dwKeySize); // pdwKeySize
  5066. if (S_OK != hr)
  5067. {
  5068. _PrintError(hr, "myGetCertSrvCSP");
  5069. dwProvType = pServer->pCSPInfo->dwProvType;
  5070. idAlg = CALG_3DES;
  5071. fMachineKeyset = pServer->pCSPInfo->fMachineKeyset;
  5072. dwKeySize = 1024;
  5073. }
  5074. else if (NULL != pwszProvNameReg && L'\0' != *pwszProvNameReg)
  5075. {
  5076. pwszProvName = pwszProvNameReg;
  5077. if (0 == lstrcmpi(pwszProvName, MS_DEF_PROV_W))
  5078. {
  5079. pwszProvName = MS_STRONG_PROV_W;
  5080. }
  5081. }
  5082. hr = SetCertSrvCSP(
  5083. TRUE, // fEncryptionCSP
  5084. pServer->pwszSanitizedName,
  5085. dwProvType,
  5086. pwszProvName,
  5087. idAlg,
  5088. fMachineKeyset,
  5089. dwKeySize); // dwKeySize
  5090. _JumpIfError(hr, error, "SetCertSrvCSP");
  5091. }
  5092. hr = S_OK;
  5093. error:
  5094. if (NULL != pwszProvNameReg)
  5095. {
  5096. LocalFree(pwszProvNameReg);
  5097. }
  5098. myLdapClose(pld, strDomainDN, strConfigDN);
  5099. if (NULL != pwszCLSIDCertGetConfig)
  5100. {
  5101. CoTaskMemFree(pwszCLSIDCertGetConfig);
  5102. }
  5103. if (NULL != pwszCRLPeriod)
  5104. {
  5105. LocalFree(pwszCRLPeriod);
  5106. }
  5107. if (NULL != pwszCRLDeltaPeriod)
  5108. {
  5109. LocalFree(pwszCRLDeltaPeriod);
  5110. }
  5111. if (NULL != pwszCLSIDCertRequest)
  5112. {
  5113. CoTaskMemFree(pwszCLSIDCertRequest);
  5114. }
  5115. if (NULL != pwszzCRLPublicationValue)
  5116. {
  5117. LocalFree(pwszzCRLPublicationValue);
  5118. }
  5119. if (NULL != pwszzCACertPublicationValue)
  5120. {
  5121. LocalFree(pwszzCACertPublicationValue);
  5122. }
  5123. if (NULL != pwszzRequestExtensionList)
  5124. {
  5125. LocalFree(pwszzRequestExtensionList);
  5126. }
  5127. if (NULL != pwszzDisableExtensionList)
  5128. {
  5129. LocalFree(pwszzDisableExtensionList);
  5130. }
  5131. if (NULL != pwszzFilesNotToRestore)
  5132. {
  5133. LocalFree(pwszzFilesNotToRestore);
  5134. }
  5135. if (NULL != hKeyBase)
  5136. {
  5137. RegCloseKey(hKeyBase);
  5138. }
  5139. CSILOG(hr, IDS_LOG_CREATE_SERVER_REG, NULL, NULL, NULL);
  5140. return(hr);
  5141. }
  5142. HRESULT
  5143. UpgradeRevocationURLReplaceParam(
  5144. IN BOOL fPolicy,
  5145. IN BOOL fMultiString,
  5146. IN WCHAR const *pwszSanitizedName,
  5147. IN WCHAR const *pwszValueName)
  5148. {
  5149. HRESULT hr;
  5150. WCHAR *pwszzValue = NULL;
  5151. WCHAR *pwsz;
  5152. BOOL fModified = FALSE;
  5153. CSASSERT(
  5154. WSZARRAYSIZE(wszFCSAPARM_CERTFILENAMESUFFIX) ==
  5155. WSZARRAYSIZE(wszFCSAPARM_CRLFILENAMESUFFIX));
  5156. // getMultiStr will read REG_SZs as well and double-terminate
  5157. hr = myGetCertRegMultiStrValue(
  5158. pwszSanitizedName,
  5159. fPolicy ? wszREGKEYPOLICYMODULES : wszREGKEYEXITMODULES,
  5160. fPolicy ? wszCLASS_CERTPOLICY : wszCLASS_CERTEXIT,
  5161. pwszValueName,
  5162. &pwszzValue);
  5163. _JumpIfErrorStr2(hr, error, "myGetCertRegMultiStrValue", pwszValueName, hr);
  5164. for (pwsz = pwszzValue; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  5165. {
  5166. WCHAR *pwszT = pwsz;
  5167. // Replace wszFCSAPARM_CERTFILENAMESUFFIX with
  5168. // wszFCSAPARM_CRLFILENAMESUFFIX. Beta 3's registry values incorrectly
  5169. // used a Cert Suffix instead of CRL Suffix.
  5170. while (TRUE)
  5171. {
  5172. DWORD i;
  5173. pwszT = wcschr(pwszT, wszFCSAPARM_CERTFILENAMESUFFIX[0]);
  5174. if (NULL == pwszT)
  5175. {
  5176. break;
  5177. }
  5178. for (i = 1; ; i++)
  5179. {
  5180. if (i == WSZARRAYSIZE(wszFCSAPARM_CERTFILENAMESUFFIX))
  5181. {
  5182. CopyMemory(
  5183. pwszT,
  5184. wszFCSAPARM_CRLFILENAMESUFFIX,
  5185. i * sizeof(WCHAR));
  5186. pwszT += i;
  5187. fModified = TRUE;
  5188. break;
  5189. }
  5190. if (pwszT[i] != wszFCSAPARM_CERTFILENAMESUFFIX[i])
  5191. {
  5192. pwszT++;
  5193. break;
  5194. }
  5195. }
  5196. }
  5197. }
  5198. if (fModified)
  5199. {
  5200. if (fMultiString)
  5201. {
  5202. // set as REG_MULTI_SZ
  5203. hr = mySetCertRegMultiStrValue(
  5204. pwszSanitizedName,
  5205. fPolicy ? wszREGKEYPOLICYMODULES : wszREGKEYEXITMODULES,
  5206. fPolicy ? wszCLASS_CERTPOLICY : wszCLASS_CERTEXIT,
  5207. pwszValueName,
  5208. pwszzValue);
  5209. _JumpIfErrorStr(hr, error, "mySetCertRegMultiStrValue", pwszValueName);
  5210. }
  5211. else
  5212. {
  5213. // set as REG_SZ
  5214. hr = mySetCertRegStrValue(
  5215. pwszSanitizedName,
  5216. fPolicy ? wszREGKEYPOLICYMODULES : wszREGKEYEXITMODULES,
  5217. fPolicy ? wszCLASS_CERTPOLICY : wszCLASS_CERTEXIT,
  5218. pwszValueName,
  5219. pwszzValue);
  5220. _JumpIfErrorStr(hr, error, "mySetCertRegStrValue", pwszValueName);
  5221. }
  5222. }
  5223. error:
  5224. if (NULL != pwszzValue)
  5225. {
  5226. LocalFree(pwszzValue);
  5227. }
  5228. CSASSERT(S_OK == hr || FAILED(hr));
  5229. return(hr);
  5230. }
  5231. HRESULT
  5232. UpgradeRevocationURLRemoveParam(
  5233. IN WCHAR const *pwszSanitizedName,
  5234. IN WCHAR const *pwszValueName)
  5235. {
  5236. HRESULT hr;
  5237. WCHAR *pwszValue = NULL;
  5238. WCHAR *pwsz;
  5239. BOOL fModified = FALSE;
  5240. WCHAR *pwszT;
  5241. hr = myGetCertRegStrValue(
  5242. pwszSanitizedName,
  5243. wszREGKEYPOLICYMODULES,
  5244. wszCLASS_CERTPOLICY,
  5245. pwszValueName,
  5246. &pwszValue);
  5247. _JumpIfErrorStr2(hr, error, "myGetCertRegStrValue", pwszValueName, hr);
  5248. pwszT = pwszValue;
  5249. // Remove wszFCSAPARM_CERTFILENAMESUFFIX from the Netscape Revocaton URL
  5250. // It should never have been written out in Beta 3's registry value.
  5251. while (TRUE)
  5252. {
  5253. DWORD i;
  5254. pwszT = wcschr(pwszT, wszFCSAPARM_CERTFILENAMESUFFIX[0]);
  5255. if (NULL == pwszT)
  5256. {
  5257. break;
  5258. }
  5259. for (i = 1; ; i++)
  5260. {
  5261. if (i == WSZARRAYSIZE(wszFCSAPARM_CERTFILENAMESUFFIX))
  5262. {
  5263. MoveMemory(
  5264. pwszT,
  5265. &pwszT[i],
  5266. (wcslen(&pwszT[i]) + 1) * sizeof(WCHAR));
  5267. pwszT += i;
  5268. fModified = TRUE;
  5269. break;
  5270. }
  5271. if (pwszT[i] != wszFCSAPARM_CERTFILENAMESUFFIX[i])
  5272. {
  5273. pwszT++;
  5274. break;
  5275. }
  5276. }
  5277. }
  5278. if (fModified)
  5279. {
  5280. hr = mySetCertRegStrValue(
  5281. pwszSanitizedName,
  5282. wszREGKEYPOLICYMODULES,
  5283. wszCLASS_CERTPOLICY,
  5284. pwszValueName,
  5285. pwszValue);
  5286. _JumpIfErrorStr(hr, error, "mySetCertRegStrValue", pwszValueName);
  5287. }
  5288. error:
  5289. if (NULL != pwszValue)
  5290. {
  5291. LocalFree(pwszValue);
  5292. }
  5293. CSASSERT(S_OK == hr || FAILED(hr));
  5294. return(hr);
  5295. }
  5296. WCHAR const *apwszB3ExitEntriesToFix[] =
  5297. {
  5298. wszREGLDAPREVOCATIONDNTEMPLATE_OLD,
  5299. NULL
  5300. };
  5301. HRESULT
  5302. UpgradeCRLPath(
  5303. WCHAR const *pwszSanitizedName)
  5304. {
  5305. HRESULT hr;
  5306. WCHAR *pwszzCRLPath = NULL;
  5307. WCHAR *pwszzFixedCRLPath = NULL;
  5308. WCHAR *pwsz;
  5309. BOOL fRenewReady = TRUE;
  5310. DWORD dwSize = 0;
  5311. // get current crl path
  5312. hr = myGetCertRegMultiStrValue(
  5313. pwszSanitizedName,
  5314. NULL,
  5315. NULL,
  5316. wszREGCRLPATH_OLD,
  5317. &pwszzCRLPath);
  5318. _JumpIfErrorStr(hr, error, "myGetCertRegStrValue", wszREGCRLPATH_OLD);
  5319. // to see if it is in renew ready format
  5320. for (pwsz = pwszzCRLPath; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  5321. {
  5322. dwSize += wcslen(pwsz) + 1;
  5323. if (NULL == wcsstr(pwsz, wszFCSAPARM_CRLFILENAMESUFFIX))
  5324. {
  5325. // found one without suffix
  5326. fRenewReady = FALSE;
  5327. // add suffix len
  5328. dwSize += WSZARRAYSIZE(wszFCSAPARM_CRLFILENAMESUFFIX);
  5329. }
  5330. }
  5331. if (!fRenewReady)
  5332. {
  5333. ++dwSize; // multi string
  5334. // at least one of crl path missed suffix
  5335. pwszzFixedCRLPath = (WCHAR*)LocalAlloc(LMEM_FIXED,
  5336. dwSize * sizeof(WCHAR));
  5337. _JumpIfOutOfMemory(hr, error, pwszzFixedCRLPath);
  5338. WCHAR *pwszPt = pwszzFixedCRLPath;
  5339. for (pwsz = pwszzCRLPath; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  5340. {
  5341. // copy over whole path 1st
  5342. wcscpy(pwszPt, pwsz);
  5343. if (NULL == wcsstr(pwszPt, wszFCSAPARM_CRLFILENAMESUFFIX))
  5344. {
  5345. // miss suffix, find file portion
  5346. WCHAR *pwszFile = wcsrchr(pwszPt, L'\\');
  5347. if (NULL == pwszFile)
  5348. {
  5349. // may be relative path, point to begin
  5350. pwszFile = pwszPt;
  5351. }
  5352. // find crl extension portion
  5353. WCHAR *pwszCRLExt = wcsrchr(pwszFile, L'.');
  5354. if (NULL != pwszCRLExt)
  5355. {
  5356. // insert suffix
  5357. wcscpy(pwszCRLExt, wszFCSAPARM_CRLFILENAMESUFFIX);
  5358. // add extension portion from original buffer
  5359. wcscat(pwszCRLExt,
  5360. pwsz + SAFE_SUBTRACT_POINTERS(pwszCRLExt, pwszPt));
  5361. }
  5362. else
  5363. {
  5364. // no crl file extension, append suffix at end
  5365. wcscat(pwszPt, wszFCSAPARM_CRLFILENAMESUFFIX);
  5366. }
  5367. }
  5368. // update pointer
  5369. pwszPt += wcslen(pwszPt) + 1;
  5370. }
  5371. // mutil string
  5372. *pwszPt = L'\0';
  5373. CSASSERT(dwSize == SAFE_SUBTRACT_POINTERS(pwszPt, pwszzFixedCRLPath) + 1);
  5374. // reset crl path with the fixed crl path
  5375. hr = mySetCertRegMultiStrValue(
  5376. pwszSanitizedName,
  5377. NULL,
  5378. NULL,
  5379. wszREGCRLPATH_OLD,
  5380. pwszzFixedCRLPath);
  5381. _JumpIfErrorStr(hr, error, "mySetCertRegMultiStrValue", wszREGCRLPATH_OLD);
  5382. }
  5383. hr = S_OK;
  5384. error:
  5385. if (NULL != pwszzCRLPath)
  5386. {
  5387. LocalFree(pwszzCRLPath);
  5388. }
  5389. if (NULL != pwszzFixedCRLPath)
  5390. {
  5391. LocalFree(pwszzFixedCRLPath);
  5392. }
  5393. return hr;
  5394. }
  5395. typedef struct _URLPREFIXSTRUCT
  5396. {
  5397. WCHAR const *pwszURLPrefix;
  5398. DWORD dwURLFlags;
  5399. } URLPREFIXSTRUCT;
  5400. //array of cdp url type and its default usage which is prefix of url
  5401. URLPREFIXSTRUCT aCDPURLPrefixList[] =
  5402. {
  5403. {L"file:", CSURL_ADDTOCERTCDP | CSURL_ADDTOFRESHESTCRL | CSURL_ADDTOCRLCDP},
  5404. {L"http:", CSURL_ADDTOCERTCDP | CSURL_ADDTOFRESHESTCRL | CSURL_ADDTOCRLCDP},
  5405. {L"ldap:", CSURL_SERVERPUBLISH | CSURL_ADDTOCERTCDP | CSURL_ADDTOFRESHESTCRL | CSURL_ADDTOCRLCDP},
  5406. {NULL, 0}
  5407. };
  5408. //array of aia url type and its default usage which is prefix of url
  5409. URLPREFIXSTRUCT aAIAURLPrefixList[] =
  5410. {
  5411. {L"file:", CSURL_ADDTOCERTCDP},
  5412. {L"http:", CSURL_ADDTOCERTCDP},
  5413. {L"ldap:", CSURL_ADDTOCERTCDP | CSURL_SERVERPUBLISH},
  5414. {NULL, 0}
  5415. };
  5416. #define wszURLPREFIXFORMAT L"%d:"
  5417. //pass an old url, determine what is prefix in a format of "XX:"
  5418. HRESULT
  5419. DetermineURLPrefixFlags(
  5420. IN BOOL fDisabled,
  5421. IN BOOL fCDP,
  5422. IN WCHAR const *pwszURL,
  5423. IN WCHAR *pwszPrefixFlags)
  5424. {
  5425. HRESULT hr;
  5426. URLPREFIXSTRUCT *pURLPrefix;
  5427. DWORD dwPathFlags;
  5428. WCHAR *pwszT;
  5429. WCHAR *pwszLower = NULL;
  5430. //default to disable
  5431. wsprintf(pwszPrefixFlags, wszURLPREFIXFORMAT, 0);
  5432. if (fDisabled)
  5433. {
  5434. //easy
  5435. goto done;
  5436. }
  5437. if (myIsFullPath(pwszURL, &dwPathFlags))
  5438. {
  5439. //local path, easy
  5440. wsprintf(pwszPrefixFlags, wszURLPREFIXFORMAT, CSURL_SERVERPUBLISH);
  5441. goto done;
  5442. }
  5443. //make lower case url string
  5444. pwszLower = (WCHAR*)LocalAlloc(LMEM_FIXED,
  5445. (wcslen(pwszURL) + 1) * sizeof(WCHAR));
  5446. if (NULL == pwszLower)
  5447. {
  5448. hr = E_OUTOFMEMORY;
  5449. _JumpError(hr, error, "LocalAlloc");
  5450. }
  5451. wcscpy(pwszLower, pwszURL);
  5452. CharLower(pwszLower);
  5453. //loop through to find out url type
  5454. for (pURLPrefix = fCDP ? aCDPURLPrefixList : aAIAURLPrefixList;
  5455. NULL != pURLPrefix->pwszURLPrefix; ++pURLPrefix)
  5456. {
  5457. pwszT = wcsstr(pwszLower, pURLPrefix->pwszURLPrefix);
  5458. if (0 == wcsncmp(pwszLower, pURLPrefix->pwszURLPrefix,
  5459. wcslen(pURLPrefix->pwszURLPrefix)))
  5460. {
  5461. //prefix appears at the begining
  5462. wsprintf(pwszPrefixFlags, wszURLPREFIXFORMAT, pURLPrefix->dwURLFlags);
  5463. goto done;
  5464. }
  5465. }
  5466. //nothing matches, keep 0 flag
  5467. done:
  5468. hr = S_OK;
  5469. error:
  5470. if (NULL != pwszLower)
  5471. {
  5472. LocalFree(pwszLower);
  5473. }
  5474. return hr;
  5475. }
  5476. //move old cdp or aia url from policy to a new location under ca
  5477. HRESULT
  5478. UpgradeMoveURLsLocation(
  5479. IN BOOL fCDP,
  5480. IN WCHAR const *pwszSanitizedName,
  5481. IN WCHAR const *pwszValueName)
  5482. {
  5483. HRESULT hr;
  5484. WCHAR *pwszzValue = NULL;
  5485. WCHAR *pwszzURLs = NULL;
  5486. BOOL fDisabled;
  5487. DWORD cURLs = 0; //count of url from multi_sz
  5488. DWORD dwLen = 0;
  5489. DWORD dwSize = 0; //total size of chars in multi_sz url exluding '-'
  5490. WCHAR *pwsz;
  5491. WCHAR *pwszT;
  5492. WCHAR *pwszNoMinus;
  5493. WCHAR wszPrefixFlags[9]; //should be enough
  5494. // get urls in the old location
  5495. hr = myGetCertRegMultiStrValue(
  5496. pwszSanitizedName,
  5497. wszREGKEYPOLICYMODULES,
  5498. wszCLASS_CERTPOLICY,
  5499. pwszValueName,
  5500. &pwszzValue);
  5501. _JumpIfErrorStr2(hr, error, "myGetCertRegMultiStrValue", pwszValueName, hr);
  5502. // fix "-" prefix for disable and count size
  5503. for (pwsz = pwszzValue; L'\0' != *pwsz; pwsz += dwLen + 1)
  5504. {
  5505. //current url length
  5506. dwLen = wcslen(pwsz);
  5507. //update size
  5508. dwSize += dwLen;
  5509. ++cURLs;
  5510. pwszNoMinus = pwsz;
  5511. while (L'-' == *pwszNoMinus)
  5512. {
  5513. //exclude prefix '-'s
  5514. --dwSize;
  5515. ++pwszNoMinus;
  5516. }
  5517. }
  5518. //allocate buffer in "XX:URL" format
  5519. pwszzURLs = (WCHAR*)LocalAlloc(LMEM_FIXED,
  5520. (dwSize + cURLs * sizeof(wszPrefixFlags) + 1) * sizeof(WCHAR));
  5521. if (NULL == pwszzURLs)
  5522. {
  5523. hr = E_OUTOFMEMORY;
  5524. _JumpError(hr, error, "LocalAlloc");
  5525. }
  5526. pwszT = pwszzURLs;
  5527. //form string in new url format
  5528. for (pwsz = pwszzValue; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  5529. {
  5530. fDisabled = FALSE;
  5531. pwszNoMinus = pwsz;
  5532. while (L'-' == *pwszNoMinus)
  5533. {
  5534. //exclude prefix '-'s
  5535. ++pwszNoMinus;
  5536. fDisabled = TRUE;
  5537. }
  5538. hr = DetermineURLPrefixFlags(fDisabled, fCDP, pwszNoMinus, wszPrefixFlags);
  5539. _JumpIfErrorStr(hr, error, "DetermineURLPrefixFlags", pwszNoMinus);
  5540. //format "xx:url"
  5541. wcscpy(pwszT, wszPrefixFlags);
  5542. wcscat(pwszT, pwszNoMinus);
  5543. //ready for next url
  5544. pwszT += wcslen(pwszT) + 1;
  5545. }
  5546. //zz
  5547. *pwszT = L'\0';
  5548. pwszT = fCDP ? wszREGCRLPUBLICATIONURLS : wszREGCACERTPUBLICATIONURLS,
  5549. //move or merge to ca
  5550. hr = mySetCertRegMultiStrValueEx(
  5551. CSREG_UPGRADE | CSREG_MERGE,
  5552. pwszSanitizedName,
  5553. NULL,
  5554. NULL,
  5555. pwszT,
  5556. pwszzURLs);
  5557. _JumpIfErrorStr(hr, error, "mySetCertRegMultiStrValue", pwszT);
  5558. //remove url under policy
  5559. hr = myDeleteCertRegValue(
  5560. pwszSanitizedName,
  5561. wszREGKEYPOLICYMODULES,
  5562. wszCLASS_CERTPOLICY,
  5563. pwszValueName);
  5564. _PrintIfErrorStr(hr, "myGetCertRegMultiStrValue", pwszValueName);
  5565. hr = S_OK;
  5566. error:
  5567. if (NULL != pwszzValue)
  5568. {
  5569. LocalFree(pwszzValue);
  5570. }
  5571. if (NULL != pwszzURLs)
  5572. {
  5573. LocalFree(pwszzURLs);
  5574. }
  5575. return(hr);
  5576. }
  5577. WCHAR const *apwszPolicyCDPEntriesToFix[] =
  5578. {
  5579. wszREGLDAPREVOCATIONCRLURL_OLD, //"LDAPRevocationCRLURL"
  5580. wszREGREVOCATIONCRLURL_OLD, //"RevocationCRLURL"
  5581. wszREGFTPREVOCATIONCRLURL_OLD, //"FTPRevocationCRLURL"
  5582. wszREGFILEREVOCATIONCRLURL_OLD, //"FileRevocationCRLURL"
  5583. NULL
  5584. };
  5585. HRESULT
  5586. myPrintIfError(
  5587. IN HRESULT hrNew,
  5588. IN HRESULT hrOld,
  5589. IN CHAR const *psz,
  5590. IN OPTIONAL WCHAR const *pwsz)
  5591. {
  5592. if (S_OK != hrNew)
  5593. {
  5594. if (NULL != pwsz)
  5595. {
  5596. _PrintErrorStr(hrNew, psz, pwsz);
  5597. }
  5598. else
  5599. {
  5600. _PrintError(hrNew, psz);
  5601. }
  5602. if (S_OK == hrOld)
  5603. {
  5604. //save only oldest err
  5605. hrOld = hrNew;
  5606. }
  5607. }
  5608. return hrOld;
  5609. }
  5610. HRESULT
  5611. UpgradePolicyCDPURLs(
  5612. IN WCHAR const *pwszSanitizedName)
  5613. {
  5614. HRESULT hr = S_OK;
  5615. HRESULT hr2;
  5616. WCHAR const **ppwsz;
  5617. for (ppwsz = apwszPolicyCDPEntriesToFix; NULL != *ppwsz; ppwsz++)
  5618. {
  5619. // all entries are multi-valued
  5620. hr2 = UpgradeRevocationURLReplaceParam(
  5621. TRUE, TRUE, pwszSanitizedName, *ppwsz);
  5622. hr = myPrintIfError(hr2, hr, "UpgradeRevocationURLReplaceParam", *ppwsz);
  5623. hr2 = UpgradeMoveURLsLocation(TRUE, pwszSanitizedName, *ppwsz);
  5624. hr = myPrintIfError(hr2, hr, "UpgradeMoveURLsLocation", *ppwsz);
  5625. }
  5626. hr2 = UpgradeRevocationURLRemoveParam(pwszSanitizedName, wszREGREVOCATIONURL);
  5627. hr = myPrintIfError(hr2, hr, "UpgradeRevocationURLRemoveParam", wszREGREVOCATIONURL);
  5628. hr2 = UpgradeCRLPath(pwszSanitizedName);
  5629. hr = myPrintIfError(hr2, hr, "UpgradeCRLPath", NULL);
  5630. return(hr);
  5631. }
  5632. WCHAR const *apwszPolicyAIAEntriesToFix[] =
  5633. {
  5634. wszREGLDAPISSUERCERTURL_OLD, //"LDAPIssuerCertURL"
  5635. wszREGISSUERCERTURL_OLD, //"IssuerCertURL"
  5636. wszREGFTPISSUERCERTURL_OLD, //"FTPIssuerCertURL"
  5637. wszREGFILEISSUERCERTURL_OLD, //"FileIssuerCertURL"
  5638. NULL
  5639. };
  5640. HRESULT
  5641. UpgradePolicyAIAURLs(
  5642. IN WCHAR const *pwszSanitizedName)
  5643. {
  5644. HRESULT hr = S_OK;
  5645. HRESULT hr2;
  5646. WCHAR const **ppwsz;
  5647. for (ppwsz = apwszPolicyAIAEntriesToFix; NULL != *ppwsz; ppwsz++)
  5648. {
  5649. // all entries are multi-valued
  5650. hr2 = UpgradeMoveURLsLocation(FALSE, pwszSanitizedName, *ppwsz);
  5651. hr = myPrintIfError(hr2, hr, "UpgradeMoveURLsLocation", *ppwsz);
  5652. }
  5653. return(hr);
  5654. }
  5655. HRESULT
  5656. UpgradeExitRevocationURLs(
  5657. IN WCHAR const *pwszSanitizedName)
  5658. {
  5659. WCHAR const **ppwsz;
  5660. for (ppwsz = apwszB3ExitEntriesToFix; NULL != *ppwsz; ppwsz++)
  5661. {
  5662. // all entries are single-valued
  5663. UpgradeRevocationURLReplaceParam(FALSE, FALSE, pwszSanitizedName, *ppwsz);
  5664. }
  5665. return(S_OK);
  5666. }
  5667. // following code to determine if current policy/exit modules are custom
  5668. // if find any custom module and assign it to
  5669. // pServer->pwszCustomPolicy/Exit
  5670. // otherwise pServer->pwszCustomPolicy/Exit = NULL means default as active
  5671. #define wszCERTSRV10POLICYPROGID L"CertificateAuthority.Policy"
  5672. #define wszCERTSRV10EXITPROGID L"CertificateAuthority.Exit"
  5673. #define wszCLSID L"ClsID\\"
  5674. #define wszINPROCSERVER32 L"\\InprocServer32"
  5675. HRESULT
  5676. DetermineServerCustomModule(
  5677. PER_COMPONENT_DATA *pComp,
  5678. IN BOOL fPolicy)
  5679. {
  5680. HRESULT hr;
  5681. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  5682. // init
  5683. if (fPolicy)
  5684. {
  5685. if (NULL != pServer->pwszCustomPolicy)
  5686. {
  5687. LocalFree(pServer->pwszCustomPolicy);
  5688. pServer->pwszCustomPolicy = NULL;
  5689. }
  5690. }
  5691. else
  5692. {
  5693. if (NULL != pServer->pwszzCustomExit)
  5694. {
  5695. LocalFree(pServer->pwszzCustomExit);
  5696. pServer->pwszzCustomExit = NULL;
  5697. }
  5698. }
  5699. // build to build
  5700. // to pass what is the current active policy
  5701. if (fPolicy)
  5702. {
  5703. // policy module
  5704. hr = myGetCertRegStrValue(
  5705. pServer->pwszSanitizedName,
  5706. wszREGKEYPOLICYMODULES,
  5707. NULL,
  5708. wszREGACTIVE,
  5709. &pServer->pwszCustomPolicy);
  5710. _JumpIfError(hr, done, "myGetCertRegStrValue");
  5711. }
  5712. else
  5713. {
  5714. // exit module
  5715. hr = myGetCertRegMultiStrValue(
  5716. pServer->pwszSanitizedName,
  5717. wszREGKEYEXITMODULES,
  5718. NULL,
  5719. wszREGACTIVE,
  5720. &pServer->pwszzCustomExit);
  5721. _JumpIfError(hr, done, "myGetCertRegStrValue");
  5722. }
  5723. done:
  5724. hr = S_OK;
  5725. //error:
  5726. return hr;
  5727. }
  5728. HRESULT
  5729. UpgradeServerRegEntries(
  5730. HWND hwnd,
  5731. PER_COMPONENT_DATA *pComp)
  5732. {
  5733. HRESULT hr;
  5734. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  5735. WCHAR *pwszCRLPeriodString = NULL;
  5736. BOOL fUseNewCRLPublish = FALSE;
  5737. DWORD dwCRLPeriodCount;
  5738. DWORD Count;
  5739. BOOL fUpgradeW2K = CS_UPGRADE_WIN2000 == pComp->UpgradeFlag;
  5740. CSASSERT(
  5741. NULL != pServer->pwszSanitizedName &&
  5742. NULL != pServer->pccUpgradeCert);
  5743. // Description:
  5744. // - if upgrade and get this point, all necessary data structure
  5745. // should be loaded and created in LoadAndDetermineServerUpgradeInfo()
  5746. // - in this module, check all different upgrade cases,
  5747. // upgrade (move) reg entries
  5748. // - remove old unused reg entries if upgrade
  5749. // Note: each of above steps applys from config level down to ca then
  5750. // to policy, etc.
  5751. // - lastly call CreateServerRegEntries with upgrade flag
  5752. // CONFIGURATION LEVEL
  5753. // CA LEVEL
  5754. hr = myGetCARegHashCount(
  5755. pServer->pwszSanitizedName,
  5756. CSRH_CASIGCERT,
  5757. &Count);
  5758. _JumpIfError(hr, error, "myGetCARegHashCount");
  5759. if (0 == Count)
  5760. {
  5761. hr = mySetCARegHash(
  5762. pServer->pwszSanitizedName,
  5763. CSRH_CASIGCERT,
  5764. 0, // iCert
  5765. pServer->pccUpgradeCert);
  5766. _JumpIfError(hr, error, "mySetCARegHash");
  5767. }
  5768. // POLICY LEVEL
  5769. {
  5770. //could fix two things, 1) W2K from B3 needs fixing token plus 2) or
  5771. // 2) W2K needs fix CDP location
  5772. hr = UpgradePolicyCDPURLs(pServer->pwszSanitizedName);
  5773. _PrintIfError(hr, "UpgradePolicyCDPURLs");
  5774. hr = UpgradePolicyAIAURLs(pServer->pwszSanitizedName);
  5775. _PrintIfError(hr, "UpgradePolicyAIAURLs");
  5776. hr = UpgradeExitRevocationURLs(pServer->pwszSanitizedName);
  5777. _PrintIfError(hr, "UpgradeExitRevocationURLs");
  5778. //UNDONE, we need move url for cdp and aia under policy to ca level
  5779. }
  5780. // EXIT LEVEL
  5781. // DELETE OLD AND UNUSED ENTRIES
  5782. hr = CreateServerRegEntries(hwnd, TRUE, pComp);
  5783. _JumpIfError(hr, error, "CreateServerRegEntries");
  5784. // hr = S_OK;
  5785. error:
  5786. if (NULL != pwszCRLPeriodString)
  5787. {
  5788. LocalFree(pwszCRLPeriodString);
  5789. }
  5790. CSILOG(hr, IDS_LOG_UPGRADE_SERVER_REG, NULL, NULL, NULL);
  5791. return(hr);
  5792. }
  5793. HRESULT
  5794. RegisterAndUnRegisterDLLs(
  5795. IN DWORD Flags,
  5796. IN PER_COMPONENT_DATA *pComp,
  5797. IN HWND hwnd)
  5798. {
  5799. HRESULT hr;
  5800. HMODULE hMod = NULL;
  5801. typedef HRESULT (STDAPICALLTYPE FNDLLREGISTERSERVER)(VOID);
  5802. FNDLLREGISTERSERVER *pfnRegister;
  5803. CHAR const *pszFuncName;
  5804. REGISTERDLL const *prd;
  5805. WCHAR wszString[MAX_PATH];
  5806. UINT errmode = 0;
  5807. BOOL fCoInit = FALSE;
  5808. hr = CoInitialize(NULL);
  5809. if (S_OK != hr && S_FALSE != hr)
  5810. {
  5811. _JumpError(hr, error, "CoInitialize");
  5812. }
  5813. fCoInit = TRUE;
  5814. errmode = SetErrorMode(SEM_FAILCRITICALERRORS);
  5815. pszFuncName = 0 == (RD_UNREGISTER & Flags)?
  5816. aszRegisterServer[0] : aszRegisterServer[1];
  5817. for (prd = g_aRegisterDll; NULL != prd->pwszDllName; prd++)
  5818. {
  5819. if ((Flags & RD_UNREGISTER) &&
  5820. ((Flags & RD_SKIPUNREGPOLICY) && (prd->Flags & RD_SKIPUNREGPOLICY) ||
  5821. (Flags & RD_SKIPUNREGEXIT) && (prd->Flags & RD_SKIPUNREGEXIT) ||
  5822. (Flags & RD_SKIPUNREGMMC) && (prd->Flags & RD_SKIPUNREGMMC)))
  5823. {
  5824. // case of upgrade path & this dll doesn't want to unreg
  5825. continue;
  5826. }
  5827. if (Flags & prd->Flags)
  5828. {
  5829. if (NULL != g_pwszArgvPath)
  5830. {
  5831. wcscpy(wszString, g_pwszArgvPath);
  5832. if (L'\0' != wszString[0] &&
  5833. L'\\' != wszString[wcslen(wszString) - 1])
  5834. {
  5835. wcscat(wszString, L"\\");
  5836. }
  5837. }
  5838. else
  5839. {
  5840. wcscpy(wszString, pComp->pwszSystem32);
  5841. }
  5842. wcscat(wszString, prd->pwszDllName);
  5843. hMod = LoadLibrary(wszString);
  5844. if (NULL == hMod)
  5845. {
  5846. hr = myHLastError();
  5847. if (0 == (RD_UNREGISTER & Flags) &&
  5848. (!(RD_WHISTLER & prd->Flags) || IsWhistler()))
  5849. {
  5850. SaveCustomMessage(pComp, wszString);
  5851. CertErrorMessageBox(
  5852. pComp->hInstance,
  5853. pComp->fUnattended,
  5854. hwnd,
  5855. IDS_ERR_DLLFUNCTION_CALL,
  5856. hr,
  5857. wszString);
  5858. _JumpErrorStr(hr, error, "DllRegisterServer", wszString);
  5859. CSILOG(hr, IDS_LOG_DLLS_REGISTERED, wszString, NULL, NULL);
  5860. _JumpErrorStr(hr, error, "LoadLibrary", wszString);
  5861. }
  5862. hr = S_OK;
  5863. continue;
  5864. }
  5865. pfnRegister = (FNDLLREGISTERSERVER *) GetProcAddress(
  5866. hMod,
  5867. pszFuncName);
  5868. if (NULL == pfnRegister)
  5869. {
  5870. hr = myHLastError();
  5871. _JumpErrorStr(hr, error, "GetProcAddress", wszString);
  5872. }
  5873. __try
  5874. {
  5875. hr = (*pfnRegister)();
  5876. }
  5877. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  5878. {
  5879. }
  5880. FreeLibrary(hMod);
  5881. hMod = NULL;
  5882. if (S_OK != hr)
  5883. {
  5884. CSILOG(
  5885. hr,
  5886. (RD_UNREGISTER & Flags)?
  5887. IDS_LOG_DLLS_UNREGISTERED : IDS_LOG_DLLS_REGISTERED,
  5888. wszString,
  5889. NULL,
  5890. NULL);
  5891. if (0 == (RD_UNREGISTER & Flags))
  5892. {
  5893. CertErrorMessageBox(
  5894. pComp->hInstance,
  5895. pComp->fUnattended,
  5896. hwnd,
  5897. IDS_ERR_DLLFUNCTION_CALL,
  5898. hr,
  5899. wszString);
  5900. _JumpErrorStr(hr, error, "DllRegisterServer", wszString);
  5901. }
  5902. else
  5903. {
  5904. _PrintErrorStr(hr, "DllUnregisterServer", wszString);
  5905. }
  5906. }
  5907. }
  5908. }
  5909. hr = S_OK;
  5910. error:
  5911. if (NULL != hMod)
  5912. {
  5913. FreeLibrary(hMod);
  5914. }
  5915. SetErrorMode(errmode);
  5916. if (fCoInit)
  5917. {
  5918. CoUninitialize();
  5919. }
  5920. if (S_OK == hr)
  5921. {
  5922. CSILOG(
  5923. hr,
  5924. (RD_UNREGISTER & Flags)?
  5925. IDS_LOG_DLLS_UNREGISTERED : IDS_LOG_DLLS_REGISTERED,
  5926. NULL,
  5927. NULL,
  5928. NULL);
  5929. }
  5930. return(hr);
  5931. }
  5932. HRESULT
  5933. CreateProgramGroups(
  5934. BOOL fClient,
  5935. PER_COMPONENT_DATA *pComp,
  5936. HWND hwnd)
  5937. {
  5938. HRESULT hr;
  5939. PROGRAMENTRY const *ppe;
  5940. WCHAR const *pwszLinkName = NULL;
  5941. DWORD Flags = fClient? PE_CLIENT : PE_SERVER;
  5942. DBGPRINT((
  5943. DBG_SS_CERTOCMI,
  5944. "CreateProgramGroups: %ws\n",
  5945. fClient? L"Client" : L"Server"));
  5946. for (ppe = g_aProgramEntry; ppe < &g_aProgramEntry[CPROGRAMENTRY]; ppe++)
  5947. {
  5948. if ((Flags & ppe->Flags) && 0 == (PE_DELETEONLY & ppe->Flags))
  5949. {
  5950. WCHAR const *pwszGroupName;
  5951. WCHAR const *pwszDescription;
  5952. WCHAR awc[MAX_PATH];
  5953. WCHAR const *pwszArgs;
  5954. wcscpy(awc, pComp->pwszSystem32);
  5955. wcscat(awc, ppe->pwszExeName);
  5956. pwszArgs = fClient? ppe->pwszClientArgs : ppe->pwszServerArgs;
  5957. if (NULL != pwszArgs)
  5958. {
  5959. wcscat(awc, L" ");
  5960. wcscat(awc, pwszArgs);
  5961. }
  5962. pwszLinkName = myLoadResourceString(ppe->uiLinkName);
  5963. if (NULL == pwszLinkName)
  5964. {
  5965. hr = myHLastError();
  5966. _JumpError(hr, error, "myLoadResourceString");
  5967. }
  5968. pwszGroupName = NULL;
  5969. if (0 != ppe->uiGroupName)
  5970. {
  5971. pwszGroupName = myLoadResourceString(ppe->uiGroupName);
  5972. if (NULL == pwszGroupName)
  5973. {
  5974. hr = myHLastError();
  5975. _JumpError(hr, error, "myLoadResourceString");
  5976. }
  5977. }
  5978. pwszDescription = NULL;
  5979. if (0 != ppe->uiDescription)
  5980. {
  5981. pwszDescription = myLoadResourceString(ppe->uiDescription);
  5982. if (NULL == pwszDescription)
  5983. {
  5984. hr = myHLastError();
  5985. _JumpError(hr, error, "myLoadResourceString");
  5986. }
  5987. }
  5988. if (!CreateLinkFile(
  5989. ppe->csidl, // CSIDL_*
  5990. pwszGroupName, // IN LPCSTR lpSubDirectory
  5991. pwszLinkName, // IN LPCSTR lpFileName
  5992. awc, // IN LPCSTR lpCommandLine
  5993. NULL, // IN LPCSTR lpIconPath
  5994. 0, // IN INT iIconIndex
  5995. NULL, // IN LPCSTR lpWorkingDirectory
  5996. 0, // IN WORD wHotKey
  5997. SW_SHOWNORMAL, // IN INT iShowCmd
  5998. pwszDescription)) // IN LPCSTR lpDescription
  5999. {
  6000. hr = myHLastError();
  6001. _PrintErrorStr(hr, "CreateLinkFile", awc);
  6002. _JumpErrorStr(hr, error, "CreateLinkFile", pwszLinkName);
  6003. }
  6004. }
  6005. }
  6006. hr = S_OK;
  6007. error:
  6008. if (S_OK != hr)
  6009. {
  6010. CertErrorMessageBox(
  6011. pComp->hInstance,
  6012. pComp->fUnattended,
  6013. hwnd,
  6014. IDS_ERR_CREATELINK,
  6015. hr,
  6016. pwszLinkName);
  6017. pComp->fShownErr = TRUE;
  6018. }
  6019. CSILOG(hr, IDS_LOG_PROGRAM_GROUPS, NULL, NULL, NULL);
  6020. return(hr);
  6021. }
  6022. HRESULT
  6023. MakeRevocationPage(
  6024. HWND hwnd,
  6025. PER_COMPONENT_DATA *pComp,
  6026. IN WCHAR const *pwszFile)
  6027. {
  6028. DWORD hr;
  6029. WCHAR *pwszASP = NULL;
  6030. WCHAR *pwszConfig = NULL;
  6031. HANDLE hFile = NULL;
  6032. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  6033. #define wszASP1 \
  6034. L"<%\r\n" \
  6035. L"Response.ContentType = \"application/x-netscape-revocation\"\r\n" \
  6036. L"serialnumber = Request.QueryString\r\n" \
  6037. L"set Admin = Server.CreateObject(\"CertificateAuthority.Admin\")\r\n" \
  6038. L"\r\n" \
  6039. L"stat = Admin.IsValidCertificate(\""
  6040. #define wszASP2 \
  6041. L"\", serialnumber)\r\n" \
  6042. L"\r\n" \
  6043. L"if stat = 3 then Response.Write(\"0\") else Response.Write(\"1\") end if\r\n" \
  6044. L"%>\r\n"
  6045. hr = myFormConfigString(pComp->pwszServerName,
  6046. pServer->pwszSanitizedName,
  6047. &pwszConfig);
  6048. _JumpIfError(hr, error, "myFormConfigString");
  6049. pwszASP = (WCHAR *) LocalAlloc(
  6050. LMEM_FIXED,
  6051. (WSZARRAYSIZE(wszASP1) +
  6052. wcslen(pwszConfig) +
  6053. WSZARRAYSIZE(wszASP2) + 1) * sizeof(WCHAR));
  6054. _JumpIfOutOfMemory(hr, error, pwszASP);
  6055. wcscpy(pwszASP, wszASP1);
  6056. wcscat(pwszASP, pwszConfig);
  6057. wcscat(pwszASP, wszASP2);
  6058. hFile = CreateFile(
  6059. pwszFile, // lpFileName
  6060. GENERIC_WRITE, // dwDesiredAccess
  6061. 0, // dwShareMode
  6062. NULL, // lpSecurityAttributes
  6063. CREATE_ALWAYS, // dwCreationDisposition
  6064. 0, // dwFlagsAndAttributes
  6065. 0); // hTemplateFile
  6066. if (INVALID_HANDLE_VALUE == hFile)
  6067. {
  6068. hr = HRESULT_FROM_WIN32(ERROR_OPEN_FAILED);
  6069. _JumpError(hr, error, "CreateFile");
  6070. }
  6071. hr = myStringToAnsiFile(hFile, pwszASP, -1);
  6072. error:
  6073. if (hFile)
  6074. CloseHandle(hFile);
  6075. if (NULL != pwszASP)
  6076. {
  6077. LocalFree(pwszASP);
  6078. }
  6079. if (NULL != pwszConfig)
  6080. {
  6081. LocalFree(pwszConfig);
  6082. }
  6083. return(hr);
  6084. }
  6085. VOID
  6086. setupDeleteFile(
  6087. IN WCHAR const *pwszDir,
  6088. IN WCHAR const *pwszFile)
  6089. {
  6090. HRESULT hr;
  6091. WCHAR *pwszFilePath = NULL;
  6092. hr = myBuildPathAndExt(pwszDir, pwszFile, NULL, &pwszFilePath);
  6093. _JumpIfError(hr, error, "myBuildPathAndExt");
  6094. if (!DeleteFile(pwszFilePath))
  6095. {
  6096. hr = myHLastError();
  6097. _PrintErrorStr2(hr, "DeleteFile", pwszFilePath, hr);
  6098. }
  6099. error:
  6100. if (NULL != pwszFilePath)
  6101. {
  6102. LocalFree(pwszFilePath);
  6103. }
  6104. }
  6105. //+------------------------------------------------------------------------
  6106. // Function: RenameMiscTargets(. . . .)
  6107. //
  6108. // Synopsis: Handles various renaming jobs from the names that things
  6109. // are given at installation time to the names that they need
  6110. // in their new homes to run properly.
  6111. //
  6112. // Arguments: None
  6113. //
  6114. // Returns: DWORD error code.
  6115. //
  6116. // History: 3/21/97 JerryK Created
  6117. //-------------------------------------------------------------------------
  6118. HRESULT
  6119. RenameMiscTargets(
  6120. HWND hwnd,
  6121. PER_COMPONENT_DATA *pComp,
  6122. BOOL fServer)
  6123. {
  6124. HRESULT hr = S_OK;
  6125. WCHAR wszAspPath[MAX_PATH]; wszAspPath[0] = L'\0';
  6126. WCHAR wszCertSrv[MAX_PATH]; wszCertSrv[0] = L'\0';
  6127. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  6128. if (fServer)
  6129. {
  6130. // Create nsrev_<CA Name>.asp
  6131. BuildPath(
  6132. wszCertSrv,
  6133. ARRAYSIZE(wszCertSrv),
  6134. pComp->pwszSystem32,
  6135. wszCERTENROLLSHAREPATH);
  6136. BuildPath(
  6137. wszAspPath,
  6138. ARRAYSIZE(wszAspPath),
  6139. wszCertSrv,
  6140. L"nsrev_");
  6141. wcscat(wszAspPath, pServer->pwszSanitizedName);
  6142. wcscat(wszAspPath, TEXT(".asp"));
  6143. CSASSERT(wcslen(wszAspPath) < ARRAYSIZE(wszAspPath));
  6144. hr = MakeRevocationPage(hwnd, pComp, wszAspPath);
  6145. if (S_OK != hr)
  6146. {
  6147. CertErrorMessageBox(
  6148. pComp->hInstance,
  6149. pComp->fUnattended,
  6150. hwnd,
  6151. IDS_ERR_CREATEFILE,
  6152. hr,
  6153. wszAspPath);
  6154. _JumpError(hr, error, "MakeRevocationPage");
  6155. }
  6156. }
  6157. error:
  6158. return(hr);
  6159. }
  6160. HRESULT
  6161. CreateCertificateService(
  6162. PER_COMPONENT_DATA *pComp,
  6163. HWND hwnd)
  6164. {
  6165. HRESULT hr;
  6166. WCHAR const *pwszDisplayName;
  6167. SERVICE_DESCRIPTION sd;
  6168. SC_HANDLE hSCManager = NULL;
  6169. SC_HANDLE hSC = NULL;
  6170. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  6171. if (NULL != pServer->pwszSharedFolder)
  6172. {
  6173. // add entry
  6174. hr = CreateConfigFiles(pServer->pwszSharedFolder, pComp, FALSE, hwnd);
  6175. if (S_OK != hr)
  6176. {
  6177. CertErrorMessageBox(
  6178. pComp->hInstance,
  6179. pComp->fUnattended,
  6180. hwnd,
  6181. IDS_ERR_CREATECERTSRVFILE,
  6182. hr,
  6183. pServer->pwszSharedFolder);
  6184. _JumpError(hr, error, "CreateConfigFiles");
  6185. }
  6186. }
  6187. if (NULL != g_pwszArgvPath)
  6188. {
  6189. wcscpy(g_wszServicePath, g_pwszArgvPath);
  6190. if (L'\0' != g_wszServicePath[0] &&
  6191. L'\\' != g_wszServicePath[wcslen(g_wszServicePath) - 1])
  6192. {
  6193. wcscat(g_wszServicePath, L"\\");
  6194. }
  6195. }
  6196. else
  6197. {
  6198. wcscpy(g_wszServicePath, pComp->pwszSystem32);
  6199. }
  6200. wcscat(g_wszServicePath, wszCERTSRVEXENAME);
  6201. hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  6202. if (NULL == hSCManager)
  6203. {
  6204. hr = myHLastError();
  6205. _JumpError(hr, error, "OpenSCManager");
  6206. }
  6207. if (NULL == g_pwszNoService)
  6208. {
  6209. pwszDisplayName = myLoadResourceString(IDS_CA_SERVICEDISPLAYNAME);
  6210. if (NULL == pwszDisplayName)
  6211. {
  6212. hr = myHLastError();
  6213. _JumpError(hr, error, "myLoadResourceString");
  6214. }
  6215. sd.lpDescription = const_cast<WCHAR *>(myLoadResourceString(
  6216. IDS_CA_SERVICEDESCRIPTION));
  6217. if (NULL == sd.lpDescription)
  6218. {
  6219. hr = myHLastError();
  6220. _JumpError(hr, error, "myLoadResourceString");
  6221. }
  6222. hSC = CreateService(
  6223. hSCManager, // hSCManager
  6224. wszSERVICE_NAME, // lpServiceName
  6225. pwszDisplayName, // lpDisplayName
  6226. SERVICE_ALL_ACCESS, // dwDesiredAccess
  6227. SERVICE_WIN32_OWN_PROCESS| // dwServiceType
  6228. (pServer->fInteractiveService?
  6229. SERVICE_INTERACTIVE_PROCESS:0),
  6230. SERVICE_AUTO_START, // dwStartType
  6231. SERVICE_ERROR_NORMAL, // dwErrorControl
  6232. g_wszServicePath, // lpBinaryPathName
  6233. NULL, // lpLoadOrderGroup
  6234. NULL, // lplpdwTagId
  6235. NULL, // lpDependencies
  6236. NULL, // lpServiceStartName
  6237. NULL); // lpPassword
  6238. if (NULL == hSC)
  6239. {
  6240. hr = myHLastError();
  6241. if (HRESULT_FROM_WIN32(ERROR_DUPLICATE_SERVICE_NAME) != hr &&
  6242. HRESULT_FROM_WIN32(ERROR_SERVICE_EXISTS) != hr)
  6243. {
  6244. CertErrorMessageBox(
  6245. pComp->hInstance,
  6246. pComp->fUnattended,
  6247. hwnd,
  6248. IDS_ERR_CREATESERVICE,
  6249. hr,
  6250. wszSERVICE_NAME);
  6251. _JumpError(hr, error, "CreateService");
  6252. }
  6253. }
  6254. if (!ChangeServiceConfig2(
  6255. hSC, // hService
  6256. SERVICE_CONFIG_DESCRIPTION, // dwInfoLevel
  6257. (VOID *) &sd)) // lpInfo
  6258. {
  6259. // This error is not critical.
  6260. hr = myHLastError();
  6261. _PrintError(hr, "ChangeServiceConfig2");
  6262. }
  6263. }
  6264. // add event log message DLL (ok, it's really an EXE) as a message source
  6265. hr = myAddLogSourceToRegistry(g_wszServicePath, wszSERVICE_NAME);
  6266. if (S_OK != hr)
  6267. {
  6268. CertErrorMessageBox(
  6269. pComp->hInstance,
  6270. pComp->fUnattended,
  6271. hwnd,
  6272. IDS_ERR_ADDSOURCETOREGISTRY,
  6273. hr,
  6274. NULL);
  6275. _JumpError(hr, error, "AddLogSourceToRegistry");
  6276. }
  6277. error:
  6278. if (NULL != hSC)
  6279. {
  6280. CloseServiceHandle(hSC);
  6281. }
  6282. if (NULL != hSCManager)
  6283. {
  6284. CloseServiceHandle(hSCManager);
  6285. }
  6286. CSILOG(hr, IDS_LOG_CREATE_SERVICE, NULL, NULL, NULL);
  6287. return(hr);
  6288. }
  6289. HRESULT
  6290. DeleteProgramGroups(
  6291. IN BOOL fAll,
  6292. IN PER_COMPONENT_DATA *pComp)
  6293. {
  6294. HRESULT hr;
  6295. PROGRAMENTRY const *ppe;
  6296. WCHAR const *pwszLinkName;
  6297. WCHAR const *pwszGroupName;
  6298. for (ppe = g_aProgramEntry; ppe < &g_aProgramEntry[CPROGRAMENTRY]; ppe++)
  6299. {
  6300. if (fAll || (PE_DELETEONLY & ppe->Flags))
  6301. {
  6302. pwszLinkName = myLoadResourceString(ppe->uiLinkName);
  6303. if (NULL == pwszLinkName)
  6304. {
  6305. hr = myHLastError();
  6306. _PrintError(hr, "myLoadResourceString");
  6307. continue;
  6308. }
  6309. pwszGroupName = NULL;
  6310. if (0 != ppe->uiGroupName)
  6311. {
  6312. pwszGroupName = myLoadResourceString(ppe->uiGroupName);
  6313. if (NULL == pwszGroupName)
  6314. {
  6315. hr = myHLastError();
  6316. _PrintError(hr, "myLoadResourceString");
  6317. continue;
  6318. }
  6319. }
  6320. if (!DeleteLinkFile(
  6321. ppe->csidl, // CSIDL_*
  6322. pwszGroupName, // IN LPCSTR lpSubDirectory
  6323. pwszLinkName, // IN LPCSTR lpFileName
  6324. FALSE)) // IN BOOL fDeleteSubDirectory
  6325. {
  6326. hr = myHLastError();
  6327. _PrintError3(
  6328. hr,
  6329. "DeleteLinkFile",
  6330. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
  6331. HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND));
  6332. }
  6333. }
  6334. }
  6335. pwszGroupName = myLoadResourceString(IDS_STARTMENU_CERTSERVER);
  6336. if (NULL == pwszGroupName)
  6337. {
  6338. hr = myHLastError();
  6339. _PrintError(hr, "myLoadResourceString");
  6340. }
  6341. else if (!DeleteGroup(pwszGroupName, TRUE))
  6342. {
  6343. hr = myHLastError();
  6344. _PrintError(hr, "DeleteGroup");
  6345. }
  6346. hr = S_OK;
  6347. //error:
  6348. return(hr);
  6349. }
  6350. HRESULT
  6351. CancelCertsrvInstallation(
  6352. HWND hwnd,
  6353. PER_COMPONENT_DATA *pComp)
  6354. {
  6355. static BOOL s_fCancelled = FALSE;
  6356. HRESULT hr;
  6357. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  6358. if (s_fCancelled)
  6359. {
  6360. goto done;
  6361. }
  6362. if (IS_SERVER_INSTALL & pComp->dwInstallStatus)
  6363. {
  6364. // uninstall will remove reg entries and others
  6365. PreUninstallCore(hwnd, pComp, FALSE);
  6366. // Note, GUI mode, we allow re-try post setup in case of cancel or failure
  6367. // but unattended mode, only allow once
  6368. UninstallCore(hwnd, pComp, 0, 0, FALSE, FALSE, !pComp->fUnattended);
  6369. if (pComp->fUnattended)
  6370. {
  6371. hr = SetSetupStatus(
  6372. NULL,
  6373. SETUP_CLIENT_FLAG | SETUP_SERVER_FLAG,
  6374. FALSE);
  6375. }
  6376. }
  6377. if (NULL != pServer)
  6378. {
  6379. if (NULL == pServer->pccExistingCert)
  6380. {
  6381. if (pServer->fSavedCAInDS)
  6382. {
  6383. // remove ca entry from ds
  6384. hr = RemoveCAInDS(pServer->pwszSanitizedName);
  6385. if (S_OK == hr)
  6386. {
  6387. pServer->fSavedCAInDS = FALSE;
  6388. }
  6389. else
  6390. {
  6391. _PrintError(hr, "RemoveCAInDS");
  6392. }
  6393. }
  6394. }
  6395. // delete the new key container, if necessary.
  6396. ClearKeyContainerName(pServer);
  6397. DisableVRootsAndShares(pComp->fCreatedVRoot, pServer->fCreatedShare);
  6398. }
  6399. DBGPRINT((DBG_SS_CERTOCM, "Certsrv setup is cancelled.\n"));
  6400. s_fCancelled = TRUE; // only once
  6401. done:
  6402. hr = S_OK;
  6403. //error:
  6404. CSILOG(hr, IDS_LOG_CANCEL_INSTALL, NULL, NULL, NULL);
  6405. return hr;
  6406. }
  6407. // Returns true if the specified period is valid. For year it
  6408. // should be in the VP_MIN,VP_MAX range. For days/weeks/months,
  6409. // we define a separate upper limit to be consistent with the
  6410. // attended setup which restricts the edit box to 4 digits.
  6411. bool IsValidPeriod(const CASERVERSETUPINFO *pServer)
  6412. {
  6413. return VP_MIN <= pServer->dwValidityPeriodCount &&
  6414. !(ENUM_PERIOD_YEARS == pServer->enumValidityPeriod &&
  6415. VP_MAX < pServer->dwValidityPeriodCount) &&
  6416. !(ENUM_PERIOD_YEARS != pServer->enumValidityPeriod &&
  6417. VP_MAX_DAYS_WEEKS_MONTHS < pServer->dwValidityPeriodCount);
  6418. }
  6419. HRESULT DeleteCertificates(const WCHAR* pwszSanitizedCAName, BOOL fRoot)
  6420. {
  6421. HRESULT hr = S_OK, hr2 = S_OK;
  6422. DWORD cCACerts, cCACert, dwNameId;
  6423. HCERTSTORE hStore = NULL;
  6424. CERT_CONTEXT const *pCACert = NULL, *pDupCert;
  6425. hr = myGetCARegHashCount(pwszSanitizedCAName, CSRH_CASIGCERT, &cCACerts);
  6426. _JumpIfError(hr, error, "myGetCARegHashCount CSRH_CASIGCERT");
  6427. hStore = CertOpenStore(
  6428. CERT_STORE_PROV_SYSTEM_W,
  6429. X509_ASN_ENCODING,
  6430. NULL, // hProv
  6431. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  6432. fRoot?wszROOT_CERTSTORE:wszCA_CERTSTORE);
  6433. for(cCACert=0; cCACert<cCACerts; cCACert++)
  6434. {
  6435. hr2 = myFindCACertByHashIndex(
  6436. hStore,
  6437. pwszSanitizedCAName,
  6438. CSRH_CASIGCERT,
  6439. cCACert,
  6440. &dwNameId,
  6441. &pCACert);
  6442. if(S_OK!=hr2)
  6443. {
  6444. hr = hr2;
  6445. _PrintIfError(hr2, "myFindCACertByHashIndex");
  6446. continue;
  6447. }
  6448. if(!CertDeleteCertificateFromStore(pCACert))
  6449. {
  6450. _PrintError(hr, "CertDeleteCertificateFromStore");
  6451. CertFreeCertificateContext(pCACert);
  6452. }
  6453. pCACert = NULL;
  6454. }
  6455. error:
  6456. CSASSERT(!pCACert);
  6457. if (NULL != hStore)
  6458. {
  6459. CertCloseStore(hStore, CERT_CLOSE_STORE_FORCE_FLAG);
  6460. }
  6461. return hr;
  6462. }
  6463. HRESULT TriggerAutoenrollment()
  6464. {
  6465. HRESULT hr = S_OK;
  6466. // must be cleaned up
  6467. CAutoHANDLE hEvent;
  6468. hEvent=OpenEvent(
  6469. EVENT_MODIFY_STATE,
  6470. false,
  6471. L"Global\\" MACHINE_AUTOENROLLMENT_TRIGGER_EVENT);
  6472. if (!hEvent)
  6473. {
  6474. hr = myHLastError();
  6475. _JumpError(hr, error, "OpenEvent");
  6476. }
  6477. if (!SetEvent(hEvent))
  6478. {
  6479. hr = myHLastError();
  6480. _JumpError(hr, error, "OpenEvent");
  6481. }
  6482. error:
  6483. return hr;
  6484. }