Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1168 lines
37 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: unattend.cpp
  8. //
  9. // Contents: handling unattended attributes
  10. //
  11. // History: 8/97 XTan
  12. //
  13. //----------------------------------------------------------------------------
  14. #include "pch.cpp"
  15. #pragma hdrstop
  16. // includes
  17. #include <assert.h>
  18. #include "cscsp.h"
  19. #include "certmsg.h"
  20. #include "usecert.h"
  21. #include "dssetup.h"
  22. #include "wizpage.h"
  23. //defines
  24. #define __dwFILE__ __dwFILE_OCMSETUP_UNATTEND_CPP__
  25. #define wszCOMPONENTS L"Components"
  26. #define wszAttrCAMACHINE L"camachine" //L"CAMachine"
  27. #define wszAttrCANAME L"caname" //L"CAName"
  28. #define wszAttrPARENTCAMACHINE L"parentcamachine" //L"ParentCAMachine"
  29. #define wszAttrPARENTCANAME L"parentcaname" //L"ParentCAName"
  30. #define wszAttrCATYPE L"catype" //L"CAType"
  31. #define wszAttrNAME L"name" //L"Name"
  32. #define wszAttrCADISTINGUISHEDNAME L"cadistinguishedname" //L"CADistinguishedName"
  33. #define wszAttrORGANIZATION L"organization" //L"Organization" // dead
  34. #define wszAttrORGANIZATIONUNIT L"organizationalunit" //L"OrganizationalUnit" // dead
  35. #define wszAttrLOCALITY L"locality" //L"Locality" // dead
  36. #define wszAttrSTATE L"state" //L"State" // dead
  37. #define wszAttrCOUNTRY L"country" //L"Country" // dead
  38. #define wszAttrDESCRIPTION L"description" //L"Description" // dead
  39. #define wszAttrEMAIL L"email" //L"Email" // dead
  40. #define wszAttrVALIDITYPERIODSTRING L"validityperiod" //L"ValidityPeriod"
  41. #define wszAttrVALIDITYPERIODCOUNT L"validityperiodunits" //L"ValidityPeriodUnits"
  42. #define wszAttrSHAREDFOLDER L"sharedfolder" //L"SharedFolder"
  43. #define wszAttrREQUESTFILE L"requestfile" //L"RequestFile"
  44. #define wszAttrCSPPROVIDER L"cspprovider" //L"CSPProvider"
  45. #define wszAttrHASHALGORITHM L"hashalgorithm" //L"HashAlgorithm"
  46. #define wszAttrKEYLENGTH L"keylength" //L"KeyLength"
  47. #define wszAttrEXISTINGKEY L"existingkey" //L"ExistingKey"
  48. #define wszAttrUSEEXISTINGCERT L"useexistingcert" //L"UseExistingCert"
  49. #define wszAttrPRESERVEDB L"preservedb" //L"PreserveDB"
  50. #define wszAttrDBDIR L"dbdir" //L"DBDir"
  51. #define wszAttrLOGDIR L"logdir" //L"LogDir"
  52. #define wszAttrINTERACTIVESERVICE L"interactive" //L"Interactive"
  53. #define wszValueENTERPRISEROOT L"enterpriseroot"
  54. #define wszValueENTERPRISESUBORDINATE L"enterprisesubordinate"
  55. #define wszValueSTANDALONEROOT L"standaloneroot"
  56. #define wszValueSTANDALONESUBORDINATE L"standalonesubordinate"
  57. #define wszValueYES L"yes"
  58. #define wszValueNO L"no"
  59. #define wszValueSHA1 L"sha1"
  60. #define wszValueMD2 L"md2"
  61. #define wszValueMD4 L"md4"
  62. #define wszValueMD5 L"md5"
  63. //typedefs
  64. // globals
  65. UNATTENDPARM aUnattendParmClient[] =
  66. {
  67. { wszAttrCAMACHINE, NULL/*pClient->pwszWebCAMachine*/ },
  68. { wszAttrCANAME, NULL/*pClient->pwszWebCAName*/ },
  69. // add more code in HookUnattendedClientAttributes if you add
  70. { NULL, NULL/*end*/ },
  71. };
  72. UNATTENDPARM aUnattendParmServer[] =
  73. {
  74. { wszAttrCATYPE, NULL/*pServer->pwszCAType*/ },
  75. { wszAttrNAME, NULL/*pServer->pwszCACommonName*/ },
  76. { wszAttrCADISTINGUISHEDNAME,NULL/*pServer->pwszCADistinguishedName*/ },
  77. /* dead params
  78. { wszAttrORGANIZATION, NULL },
  79. { wszAttrORGANIZATIONUNIT, NULL },
  80. { wszAttrLOCALITY, NULL },
  81. { wszAttrSTATE, NULL },
  82. { wszAttrCOUNTRY, NULL },
  83. { wszAttrDESCRIPTION, NULL },
  84. { wszAttrEMAIL, NULL },*/
  85. { wszAttrVALIDITYPERIODCOUNT, NULL/*pServer->pwszValidityPeriodCount*/ },
  86. { wszAttrVALIDITYPERIODSTRING, NULL/*pServer->pwszValidityPeriodString*/ },
  87. { wszAttrSHAREDFOLDER, NULL/*pServer->pwszSharedFolder*/ },
  88. { wszAttrREQUESTFILE, NULL/*pServer->pwszRequestFile*/ },
  89. { wszAttrCSPPROVIDER, NULL/*pServer->pwszProvName*/ },
  90. { wszAttrHASHALGORITHM, NULL/*pServer->pwszHashAlgorithm*/ },
  91. { wszAttrKEYLENGTH, NULL/*pServer->pwszKeyLength*/ },
  92. { wszAttrEXISTINGKEY, NULL/*pServer->pwszKeyContainerName*/ },
  93. { wszAttrUSEEXISTINGCERT, NULL/*pServer->pwszUseExistingCert*/ },
  94. { wszAttrPRESERVEDB, NULL/*pServer->pwszPreserveDB*/ },
  95. { wszAttrPARENTCAMACHINE, NULL/*pServer->pwszParentCAMachine*/ },
  96. { wszAttrPARENTCANAME, NULL/*pServer->pwszParentCAName*/ },
  97. { wszAttrDBDIR, NULL/*pServer->pwszDBDirectory*/ },
  98. { wszAttrLOGDIR, NULL/*pServer->pwszLogDirectory*/ },
  99. { wszAttrINTERACTIVESERVICE, NULL/*pServer->pwszInteractiveService*/ },
  100. // add more code in HookUnattendedServerAttributes if you add
  101. { NULL, NULL/*end*/ },
  102. };
  103. HRESULT
  104. HookUnattendedClientAttributes(
  105. IN OUT PER_COMPONENT_DATA *pComp,
  106. IN OUT const SUBCOMP *pClientComp)
  107. {
  108. HRESULT hr;
  109. DWORD i;
  110. CAWEBCLIENTSETUPINFO *pClient = pComp->CA.pClient;
  111. for (i = 0; NULL != pClientComp->aUnattendParm[i].pwszName; ++i)
  112. {
  113. if (0 == LSTRCMPIS(
  114. pClientComp->aUnattendParm[i].pwszName,
  115. wszAttrCAMACHINE))
  116. {
  117. pClientComp->aUnattendParm[i].ppwszValue =
  118. &pClient->pwszWebCAMachine;
  119. }
  120. else if (0 == LSTRCMPIS(
  121. pClientComp->aUnattendParm[i].pwszName,
  122. wszAttrCANAME))
  123. {
  124. pClientComp->aUnattendParm[i].ppwszValue =
  125. &pClient->pwszWebCAName;
  126. }
  127. else
  128. {
  129. hr = E_INVALIDARG;
  130. _JumpError(hr, error, "Internal error, incorrect attr.");
  131. }
  132. }
  133. hr = S_OK;
  134. error:
  135. return hr;
  136. }
  137. HRESULT
  138. HookUnattendedServerAttributes(
  139. IN OUT PER_COMPONENT_DATA *pComp,
  140. IN OUT const SUBCOMP *pServerComp)
  141. {
  142. HRESULT hr;
  143. DWORD i;
  144. CASERVERSETUPINFO *pServer = (pComp->CA).pServer;
  145. for (i = 0; NULL != pServerComp->aUnattendParm[i].pwszName; ++i)
  146. {
  147. if (0 == LSTRCMPIS(
  148. pServerComp->aUnattendParm[i].pwszName,
  149. wszAttrCATYPE))
  150. {
  151. pServerComp->aUnattendParm[i].ppwszValue =
  152. &pServer->pwszCAType;
  153. }
  154. else if (0 == LSTRCMPIS(
  155. pServerComp->aUnattendParm[i].pwszName,
  156. wszAttrNAME))
  157. {
  158. pServerComp->aUnattendParm[i].ppwszValue =
  159. &pServer->pwszCACommonName;
  160. }
  161. else if (0 == LSTRCMPIS(
  162. pServerComp->aUnattendParm[i].pwszName,
  163. wszAttrCADISTINGUISHEDNAME))
  164. {
  165. pServerComp->aUnattendParm[i].ppwszValue =
  166. &pServer->pwszFullCADN;
  167. }
  168. else if (0 == LSTRCMPIS(
  169. pServerComp->aUnattendParm[i].pwszName,
  170. wszAttrORGANIZATION))
  171. {
  172. // dead
  173. }
  174. else if (0 == LSTRCMPIS(
  175. pServerComp->aUnattendParm[i].pwszName,
  176. wszAttrORGANIZATIONUNIT))
  177. {
  178. // dead
  179. }
  180. else if (0 == LSTRCMPIS(
  181. pServerComp->aUnattendParm[i].pwszName,
  182. wszAttrLOCALITY))
  183. {
  184. // dead
  185. }
  186. else if (0 == LSTRCMPIS(
  187. pServerComp->aUnattendParm[i].pwszName,
  188. wszAttrSTATE))
  189. {
  190. // dead
  191. }
  192. else if (0 == LSTRCMPIS(
  193. pServerComp->aUnattendParm[i].pwszName,
  194. wszAttrCOUNTRY))
  195. {
  196. // dead
  197. }
  198. else if (0 == LSTRCMPIS(
  199. pServerComp->aUnattendParm[i].pwszName,
  200. wszAttrDESCRIPTION))
  201. {
  202. // dead
  203. }
  204. else if (0 == LSTRCMPIS(
  205. pServerComp->aUnattendParm[i].pwszName,
  206. wszAttrEMAIL))
  207. {
  208. // dead
  209. }
  210. else if (0 == LSTRCMPIS(
  211. pServerComp->aUnattendParm[i].pwszName,
  212. wszAttrVALIDITYPERIODCOUNT))
  213. {
  214. pServerComp->aUnattendParm[i].ppwszValue =
  215. &pServer->pwszValidityPeriodCount;
  216. }
  217. else if (0 == LSTRCMPIS(
  218. pServerComp->aUnattendParm[i].pwszName,
  219. wszAttrVALIDITYPERIODSTRING))
  220. {
  221. pServerComp->aUnattendParm[i].ppwszValue =
  222. &pServer->pwszValidityPeriodString;
  223. }
  224. else if (0 == LSTRCMPIS(
  225. pServerComp->aUnattendParm[i].pwszName,
  226. wszAttrSHAREDFOLDER))
  227. {
  228. pServerComp->aUnattendParm[i].ppwszValue =
  229. &pServer->pwszSharedFolder;
  230. }
  231. else if (0 == LSTRCMPIS(
  232. pServerComp->aUnattendParm[i].pwszName,
  233. wszAttrREQUESTFILE))
  234. {
  235. pServerComp->aUnattendParm[i].ppwszValue =
  236. &pServer->pwszRequestFile;
  237. }
  238. else if (0 == LSTRCMPIS(
  239. pServerComp->aUnattendParm[i].pwszName,
  240. wszAttrCSPPROVIDER))
  241. {
  242. pServerComp->aUnattendParm[i].ppwszValue =
  243. &pServer->pCSPInfo->pwszProvName;
  244. }
  245. else if (0 == LSTRCMPIS(
  246. pServerComp->aUnattendParm[i].pwszName,
  247. wszAttrHASHALGORITHM))
  248. {
  249. pServerComp->aUnattendParm[i].ppwszValue =
  250. &pServer->pwszHashAlgorithm;
  251. }
  252. else if (0 == LSTRCMPIS(
  253. pServerComp->aUnattendParm[i].pwszName,
  254. wszAttrKEYLENGTH))
  255. {
  256. pServerComp->aUnattendParm[i].ppwszValue =
  257. &pServer->pwszKeyLength;
  258. }
  259. else if (0 == LSTRCMPIS(
  260. pServerComp->aUnattendParm[i].pwszName,
  261. wszAttrEXISTINGKEY))
  262. {
  263. pServerComp->aUnattendParm[i].ppwszValue =
  264. &pServer->pwszKeyContainerName;
  265. }
  266. else if (0 == LSTRCMPIS(
  267. pServerComp->aUnattendParm[i].pwszName,
  268. wszAttrUSEEXISTINGCERT))
  269. {
  270. pServerComp->aUnattendParm[i].ppwszValue =
  271. &pServer->pwszUseExistingCert;
  272. }
  273. else if (0 == LSTRCMPIS(
  274. pServerComp->aUnattendParm[i].pwszName,
  275. wszAttrPRESERVEDB))
  276. {
  277. pServerComp->aUnattendParm[i].ppwszValue =
  278. &pServer->pwszPreserveDB;
  279. }
  280. else if (0 == LSTRCMPIS(
  281. pServerComp->aUnattendParm[i].pwszName,
  282. wszAttrPARENTCAMACHINE))
  283. {
  284. pServerComp->aUnattendParm[i].ppwszValue =
  285. &pServer->pwszParentCAMachine;
  286. }
  287. else if (0 == LSTRCMPIS(
  288. pServerComp->aUnattendParm[i].pwszName,
  289. wszAttrPARENTCANAME))
  290. {
  291. pServerComp->aUnattendParm[i].ppwszValue =
  292. &pServer->pwszParentCAName;
  293. }
  294. else if (0 == LSTRCMPIS(
  295. pServerComp->aUnattendParm[i].pwszName,
  296. wszAttrDBDIR))
  297. {
  298. pServerComp->aUnattendParm[i].ppwszValue =
  299. &pServer->pwszDBDirectory;
  300. }
  301. else if (0 == LSTRCMPIS(
  302. pServerComp->aUnattendParm[i].pwszName,
  303. wszAttrLOGDIR))
  304. {
  305. pServerComp->aUnattendParm[i].ppwszValue =
  306. &pServer->pwszLogDirectory;
  307. }
  308. else if (0 == LSTRCMPIS(
  309. pServerComp->aUnattendParm[i].pwszName,
  310. wszAttrINTERACTIVESERVICE))
  311. {
  312. pServerComp->aUnattendParm[i].ppwszValue =
  313. &pServer->pwszInteractiveService;
  314. }
  315. else
  316. {
  317. hr = E_INVALIDARG;
  318. _JumpError(hr, error, "Internal error, incorrect attr.");
  319. }
  320. }
  321. hr = S_OK;
  322. error:
  323. return hr;
  324. }
  325. HRESULT
  326. certocmRetrieveUnattendedText(
  327. IN WCHAR const *pwszComponent,
  328. IN WCHAR const *pwszSubComponent,
  329. IN PER_COMPONENT_DATA *pComp)
  330. {
  331. HRESULT hr;
  332. SUBCOMP *psc;
  333. WCHAR *pwsz = NULL;
  334. WCHAR *pwszLoad;
  335. HANDLE hUnattendedFile = (*pComp->HelperRoutines.GetInfHandle)(
  336. INFINDEX_UNATTENDED,
  337. pComp->HelperRoutines.OcManagerContext);
  338. psc = TranslateSubComponent(pwszComponent, pwszSubComponent);
  339. if (NULL == psc)
  340. {
  341. hr = E_INVALIDARG;
  342. _JumpError(hr, error, "Internal error, unsupported component");
  343. }
  344. psc->fInstallUnattend = FALSE;
  345. hr = certocmReadInfString(
  346. hUnattendedFile,
  347. wszCOMPONENTS,
  348. pwszSubComponent,
  349. &pwsz);
  350. CSILOG(hr, IDS_LOG_UNATTENDED_ATTRIBUTE, pwszSubComponent, pwsz, NULL);
  351. _JumpIfError(hr, error, "certocmReadInfString");
  352. if (0 == LSTRCMPIS(pwsz, L"DEFAULT"))
  353. {
  354. psc->fInstallUnattend = psc->fDefaultInstallUnattend;
  355. }
  356. else
  357. {
  358. psc->fInstallUnattend = 0 == LSTRCMPIS(pwsz, L"ON");
  359. }
  360. if (psc->fInstallUnattend)
  361. {
  362. DWORD i;
  363. for (i = 0; NULL != psc->aUnattendParm[i].pwszName; i++)
  364. {
  365. pwszLoad = NULL;
  366. hr = certocmReadInfString(
  367. hUnattendedFile,
  368. psc->pwszSubComponent,
  369. psc->aUnattendParm[i].pwszName,
  370. &pwszLoad);
  371. if (S_OK != hr || NULL == pwszLoad)
  372. {
  373. // allow missing attributes
  374. _PrintErrorStr(
  375. hr,
  376. "Ignoring certocmReadInfString",
  377. psc->aUnattendParm[i].pwszName);
  378. continue;
  379. }
  380. if (0x0 == pwszLoad[0])
  381. {
  382. // if a attribute is given as empty, put it in log
  383. CSILOG(
  384. hr,
  385. IDS_LOG_EMPTY_UNATTENDED_ATTRIBUTE,
  386. psc->aUnattendParm[i].pwszName,
  387. NULL,
  388. NULL);
  389. // continue to take default
  390. LocalFree(pwszLoad);
  391. continue;
  392. }
  393. if (NULL != psc->aUnattendParm[i].ppwszValue &&
  394. NULL != *(psc->aUnattendParm[i].ppwszValue) )
  395. {
  396. // free old or default attributes
  397. LocalFree(*(psc->aUnattendParm[i].ppwszValue));
  398. }
  399. // get new
  400. *(psc->aUnattendParm[i].ppwszValue) = pwszLoad;
  401. CSILOG(
  402. S_OK,
  403. IDS_LOG_UNATTENDED_ATTRIBUTE,
  404. psc->aUnattendParm[i].pwszName,
  405. pwszLoad,
  406. NULL);
  407. }
  408. }
  409. hr = S_OK;
  410. error:
  411. if (NULL != pwsz)
  412. {
  413. LocalFree(pwsz);
  414. }
  415. return hr;
  416. }
  417. HRESULT BuildDistinguishedName(
  418. LPCWSTR pcwszCN,
  419. LPWSTR *ppwszDN)
  420. {
  421. HRESULT hr = S_OK;
  422. LPWSTR pwszDN = NULL;
  423. LPWSTR pwszMachineDN = NULL;
  424. LPCWSTR pcwszCNEqual = L"CN=";
  425. DWORD dwLen = 0;
  426. CSASSERT(pcwszCN);
  427. CSASSERT(ppwszDN);
  428. myGetComputerObjectName(NameFullyQualifiedDN, &pwszMachineDN);
  429. //ignore failure
  430. dwLen = wcslen(pcwszCNEqual)+wcslen(pcwszCN)+1;
  431. if(pwszMachineDN)
  432. {
  433. dwLen += wcslen(pwszMachineDN)+1; // add 1 for comma
  434. }
  435. dwLen *= sizeof(WCHAR);
  436. pwszDN = (LPWSTR)LocalAlloc(LMEM_FIXED, dwLen);
  437. _JumpIfAllocFailed(pwszDN, error);
  438. wcscpy(pwszDN, pcwszCNEqual);
  439. wcscat(pwszDN, pcwszCN);
  440. if (pwszMachineDN)
  441. {
  442. _wcsupr(pwszMachineDN);
  443. WCHAR *pwszFirstDCComponent = wcsstr(pwszMachineDN, L"DC=");
  444. if (pwszFirstDCComponent != NULL)
  445. {
  446. wcscat(pwszDN, L",");
  447. wcscat(pwszDN, pwszFirstDCComponent);
  448. }
  449. }
  450. *ppwszDN = pwszDN;
  451. error:
  452. LOCAL_FREE(pwszMachineDN);
  453. return hr;
  454. }
  455. HRESULT
  456. PrepareServerUnattendedAttributes(
  457. HWND hwnd,
  458. PER_COMPONENT_DATA *pComp)
  459. {
  460. HRESULT hr;
  461. CASERVERSETUPINFO *pServer = (pComp->CA).pServer;
  462. BOOL fCoInit = FALSE;
  463. BOOL fNotContinue = FALSE;
  464. BOOL fValidDigitString;
  465. WCHAR *pwszConfig = NULL;
  466. // determine CA type
  467. if (NULL != pServer->pwszCAType)
  468. {
  469. // case insensitive
  470. if (0 == LSTRCMPIS(pServer->pwszCAType, wszValueENTERPRISEROOT))
  471. {
  472. pServer->CAType = ENUM_ENTERPRISE_ROOTCA;
  473. }
  474. else if (0 == LSTRCMPIS(pServer->pwszCAType, wszValueENTERPRISESUBORDINATE))
  475. {
  476. pServer->CAType = ENUM_ENTERPRISE_SUBCA;
  477. }
  478. else if (0 == LSTRCMPIS(pServer->pwszCAType, wszValueSTANDALONEROOT))
  479. {
  480. pServer->CAType = ENUM_STANDALONE_ROOTCA;
  481. }
  482. else if (0 == LSTRCMPIS(pServer->pwszCAType, wszValueSTANDALONESUBORDINATE))
  483. {
  484. pServer->CAType = ENUM_STANDALONE_SUBCA;
  485. }
  486. else
  487. {
  488. // unknown ca type in unattended file
  489. hr = E_INVALIDARG;
  490. CSILOG(hr, IDS_LOG_BAD_CATYPE, pServer->pwszCAType, NULL, NULL);
  491. _JumpError(hr, error, "unknown ca type in unattended file");
  492. }
  493. }
  494. // determine if ca type and DS combination is legal
  495. if (IsEnterpriseCA(pServer->CAType))
  496. {
  497. // enterprise cas require DS
  498. if (!pServer->fUseDS)
  499. {
  500. // no ds, let it failure
  501. hr = E_INVALIDARG;
  502. CSILOG(hr, IDS_LOG_ENTERPRISE_NO_DS, NULL, NULL, NULL);
  503. _JumpError(hr, error, "No DS is available for enterprise CA. Either select standalone or install DS first");
  504. }
  505. }
  506. // build full CA DN
  507. if(EmptyString(pServer->pwszCACommonName))
  508. {
  509. hr = E_INVALIDARG;
  510. CSILOG(hr, IDS_LOG_CA_NAME_REQUIRED, NULL, NULL, NULL);
  511. _JumpError(hr, error, "CA name not specified");
  512. }
  513. if(!EmptyString(pServer->pwszFullCADN))
  514. {
  515. LPWSTR pwszTempFullName;
  516. hr = BuildFullDN(
  517. pServer->pwszCACommonName,
  518. pServer->pwszFullCADN,
  519. &pwszTempFullName);
  520. _JumpIfError(hr, error, "BuildFullDN");
  521. LocalFree(pServer->pwszFullCADN);
  522. pServer->pwszFullCADN = pwszTempFullName;
  523. }
  524. else
  525. {
  526. hr = BuildDistinguishedName(
  527. pServer->pwszCACommonName,
  528. &pServer->pwszFullCADN);
  529. _JumpIfError(hr, error, "BuildDistinguishedName");
  530. }
  531. // determine advance attributes
  532. hr = csiGetProviderTypeFromProviderName(
  533. pServer->pCSPInfo->pwszProvName,
  534. &pServer->pCSPInfo->dwProvType);
  535. _JumpIfError(hr, error, "csiGetProviderTypeFromProviderName");
  536. if (NULL != pServer->pwszHashAlgorithm)
  537. {
  538. // case insensitive
  539. if (0 == LSTRCMPIS(pServer->pwszHashAlgorithm, wszValueSHA1))
  540. {
  541. pServer->pHashInfo->idAlg = CALG_SHA1;
  542. }
  543. else if (0 == LSTRCMPIS(pServer->pwszHashAlgorithm, wszValueMD2))
  544. {
  545. pServer->pHashInfo->idAlg = CALG_MD2;
  546. }
  547. else if (0 == LSTRCMPIS(pServer->pwszHashAlgorithm, wszValueMD4))
  548. {
  549. pServer->pHashInfo->idAlg = CALG_MD4;
  550. }
  551. else if (0 == LSTRCMPIS(pServer->pwszHashAlgorithm, wszValueMD5))
  552. {
  553. pServer->pHashInfo->idAlg = CALG_MD5;
  554. }
  555. else
  556. {
  557. // undone, support oid ???
  558. // otherwise convert to calg id
  559. pServer->pHashInfo->idAlg = myWtoI(
  560. pServer->pwszHashAlgorithm,
  561. &fValidDigitString);
  562. }
  563. }
  564. // update algorithm oid anyway (for any changes from csp name, type, hash)
  565. if (NULL != pServer->pszAlgId)
  566. {
  567. // free old
  568. LocalFree(pServer->pszAlgId);
  569. }
  570. hr = myGetSigningOID(
  571. NULL, // hProv
  572. pServer->pCSPInfo->pwszProvName,
  573. pServer->pCSPInfo->dwProvType,
  574. pServer->pHashInfo->idAlg,
  575. &pServer->pszAlgId);
  576. _JumpIfError(hr, error, "myGetSigningOID");
  577. if (NULL != pServer->pwszKeyLength)
  578. {
  579. pServer->dwKeyLength = myWtoI(
  580. pServer->pwszKeyLength,
  581. &fValidDigitString);
  582. }
  583. // Import from PFX file?
  584. if(NULL != pServer->pwszPFXFile)
  585. {
  586. hr = ImportPFXAndUpdateCSPInfo(
  587. hwnd,
  588. pComp);
  589. _JumpIfError(hr, error, "ImportPFXAndUpdateCSPInfo");
  590. }
  591. if (NULL != pServer->pwszKeyContainerName)
  592. {
  593. if (NULL != pServer->pwszKeyLength)
  594. {
  595. CSILOG(hr, IDS_LOG_IGNORE_KEYLENGTH, NULL, NULL, NULL);
  596. _PrintError(0, "Defined key length is ignored because of reusing key");
  597. }
  598. // to revert key container name to common name
  599. if (NULL != pServer->pwszCACommonName)
  600. {
  601. LocalFree(pServer->pwszCACommonName);
  602. pServer->pwszCACommonName = NULL;
  603. }
  604. hr = myRevertSanitizeName(pServer->pwszKeyContainerName,
  605. &pServer->pwszCACommonName);
  606. _JumpIfError(hr, error, "myRevertSanitizeName");
  607. }
  608. // set preserveDB flag
  609. pServer->fPreserveDB = FALSE;
  610. if (NULL != pServer->pwszPreserveDB)
  611. {
  612. // case insensitive
  613. if (0 == LSTRCMPIS(pServer->pwszPreserveDB, wszValueYES))
  614. {
  615. pServer->fPreserveDB = TRUE;
  616. }
  617. }
  618. // set fInteractiveService flag
  619. pServer->fInteractiveService = FALSE;
  620. if (NULL != pServer->pwszInteractiveService)
  621. {
  622. // case insensitive
  623. if (0 == LSTRCMPIS(pServer->pwszInteractiveService, wszValueYES))
  624. {
  625. pServer->fInteractiveService = TRUE;
  626. }
  627. }
  628. // ca idinfo attributes
  629. // Reuse cert?
  630. if (NULL!=pServer->pwszUseExistingCert &&
  631. 0==LSTRCMPIS(pServer->pwszUseExistingCert, wszValueYES))
  632. {
  633. //
  634. // User wants to reuse an existing cert
  635. //
  636. // must have a key container name to reuse a cert
  637. if (NULL==pServer->pwszKeyContainerName) {
  638. hr=E_INVALIDARG;
  639. CSILOG(hr, IDS_LOG_REUSE_CERT_NO_REUSE_KEY, NULL, NULL, NULL);
  640. _JumpError(hr, error, "cannot reuse ca cert without reuse key");
  641. }
  642. // see if a matching certificate exists
  643. CERT_CONTEXT const * pccExistingCert;
  644. hr = FindCertificateByKey(pServer, &pccExistingCert);
  645. if (S_OK != hr)
  646. {
  647. CSILOG(hr, IDS_LOG_NO_CERT, NULL, NULL, NULL);
  648. _JumpError(hr, error, "FindCertificateByKey");
  649. }
  650. // use the matching cert
  651. hr = SetExistingCertToUse(pServer, pccExistingCert);
  652. _JumpIfError(hr, error, "SetExistingCertToUse");
  653. } else {
  654. //
  655. // User does not want to reuse an existing cert
  656. // Get the information that we would have pulled from the cert
  657. //
  658. // must reuse an existing cert to preserve the DB
  659. if (pServer->fPreserveDB){
  660. hr = E_INVALIDARG;
  661. CSILOG(hr, IDS_LOG_REUSE_DB_WITHOUT_REUSE_CERT, NULL, NULL, NULL);
  662. _JumpError(hr, error, "cannot preserve DB if don't reuse both key and ca cert");
  663. }
  664. // determine extended idinfo attributes
  665. // validity period
  666. DWORD dwValidityPeriodCount;
  667. ENUM_PERIOD enumValidityPeriod = ENUM_PERIOD_INVALID;
  668. BOOL fSwap = FALSE;
  669. if (NULL != pServer->pwszValidityPeriodCount ||
  670. NULL != pServer->pwszValidityPeriodString)
  671. {
  672. hr = myInfGetValidityPeriod(
  673. NULL, // hInf
  674. pServer->pwszValidityPeriodCount,
  675. pServer->pwszValidityPeriodString,
  676. &dwValidityPeriodCount,
  677. &enumValidityPeriod,
  678. &fSwap);
  679. _JumpIfError(hr, error, "myGetValidityPeriod");
  680. if (ENUM_PERIOD_INVALID != enumValidityPeriod)
  681. {
  682. pServer->enumValidityPeriod = enumValidityPeriod;
  683. }
  684. if (0 != dwValidityPeriodCount)
  685. {
  686. pServer->dwValidityPeriodCount = dwValidityPeriodCount;
  687. }
  688. }
  689. if (!IsValidPeriod(pServer))
  690. {
  691. hr = E_INVALIDARG;
  692. CSILOG(
  693. hr,
  694. IDS_LOG_BAD_VALIDITY_PERIOD_COUNT,
  695. pServer->pwszValidityPeriodCount,
  696. NULL,
  697. &pServer->dwValidityPeriodCount);
  698. _JumpError(hr, error, "validity period count");
  699. }
  700. pServer->NotAfter = pServer->NotBefore;
  701. myMakeExprDateTime(
  702. &pServer->NotAfter,
  703. pServer->dwValidityPeriodCount,
  704. pServer->enumValidityPeriod);
  705. //if swap, swap pointer before validation
  706. if (fSwap)
  707. {
  708. WCHAR *pwszTemp = pServer->pwszValidityPeriodCount;
  709. pServer->pwszValidityPeriodCount = pServer->pwszValidityPeriodString;
  710. pServer->pwszValidityPeriodString = pwszTemp;
  711. }
  712. //the following WizardPageValidation requires
  713. //pServer->pwszValidityPeriodCount so load from count before validation
  714. if (NULL == pServer->pwszValidityPeriodCount)
  715. {
  716. WCHAR wszCount[10]; //should be enough
  717. wsprintf(wszCount, L"%d", pServer->dwValidityPeriodCount);
  718. pServer->pwszValidityPeriodCount = (WCHAR*)LocalAlloc(LMEM_FIXED,
  719. (wcslen(wszCount) + 1) * sizeof(WCHAR));
  720. _JumpIfOutOfMemory(hr, error, pServer->pwszValidityPeriodCount);
  721. wcscpy(pServer->pwszValidityPeriodCount, wszCount);
  722. }
  723. // hook with g_aIdPageString
  724. hr = HookIdInfoPageStrings(g_aIdPageString, pServer);
  725. _JumpIfError(hr, error, "HookIdInfoPageStrings");
  726. hr = WizardPageValidation(
  727. pComp->hInstance,
  728. pComp->fUnattended,
  729. NULL,
  730. g_aIdPageString);
  731. _JumpIfError(hr, error, "WizardPageValidation");
  732. // make sure no invalid rdn characters
  733. if (IsAnyInvalidRDN(NULL, pComp))
  734. {
  735. hr = E_INVALIDARG;
  736. CSILOG(
  737. hr,
  738. IDS_LOG_BAD_OR_MISSING_CANAME,
  739. pServer->pwszCACommonName,
  740. NULL,
  741. NULL);
  742. _JumpError(hr, error, "Invalid RDN characters");
  743. }
  744. } // <- End if reuse/not-reuse cert
  745. // determine CA name
  746. if (NULL != pServer->pwszSanitizedName)
  747. {
  748. // free old
  749. LocalFree(pServer->pwszSanitizedName);
  750. pServer->pwszSanitizedName = NULL;
  751. }
  752. // derive ca name from common name
  753. hr = mySanitizeName(
  754. pServer->pwszCACommonName,
  755. &(pServer->pwszSanitizedName) );
  756. _JumpIfError(hr, error, "mySanitizeName");
  757. if (MAX_PATH <= wcslen(pServer->pwszSanitizedName) + cwcSUFFIXMAX)
  758. {
  759. hr = CO_E_PATHTOOLONG;
  760. CSILOG(
  761. hr,
  762. IDS_LOG_CANAME_TOO_LONG,
  763. pServer->pwszSanitizedName,
  764. NULL,
  765. NULL);
  766. _JumpErrorStr(hr, error, "CA Name", pServer->pwszSanitizedName);
  767. }
  768. // store attributes
  769. hr = StorePageValidation(NULL, pComp, &fNotContinue);
  770. _JumpIfError(hr, error, "StorePageValidation");
  771. if (fNotContinue)
  772. {
  773. hr = S_FALSE;
  774. _JumpError(hr, error, "StorePageValidation failed");
  775. }
  776. // ca cert file name
  777. if (NULL != pServer->pwszCACertFile)
  778. {
  779. // free old one
  780. LocalFree(pServer->pwszCACertFile);
  781. }
  782. hr = csiBuildCACertFileName(
  783. pComp->hInstance,
  784. hwnd,
  785. pComp->fUnattended,
  786. pServer->pwszSharedFolder,
  787. pServer->pwszSanitizedName,
  788. L".crt",
  789. 0, // CANAMEIDTOICERT(pServer->dwCertNameId),
  790. &pServer->pwszCACertFile);
  791. if (S_OK != hr)
  792. {
  793. CSILOG(
  794. hr,
  795. IDS_LOG_PATH_CAFILE_BUILD_FAIL,
  796. pServer->pwszSharedFolder, //likely by invalid shared folder path
  797. NULL,
  798. NULL);
  799. _JumpError(hr, error, "csiBuildFileName");
  800. }
  801. // validate path length
  802. if (MAX_PATH <= wcslen(pServer->pwszCACertFile) + cwcSUFFIXMAX)
  803. {
  804. hr = CO_E_PATHTOOLONG;
  805. CSILOG(
  806. hr,
  807. IDS_LOG_PATH_TOO_LONG_CANAME,
  808. pServer->pwszCACertFile,
  809. NULL,
  810. NULL);
  811. _JumpErrorStr(hr, error, "csiBuildFileName", pServer->pwszCACertFile);
  812. }
  813. // request attributes
  814. // if subordinate ca, determine online or request file
  815. if (IsSubordinateCA(pServer->CAType))
  816. {
  817. // default
  818. pServer->fSaveRequestAsFile = TRUE;
  819. if (NULL != pServer->pwszParentCAMachine)
  820. {
  821. // online case
  822. pServer->fSaveRequestAsFile = FALSE;
  823. hr = CoInitialize(NULL);
  824. if (S_OK != hr && S_FALSE != hr)
  825. {
  826. _JumpError(hr, error, "CoInitialize");
  827. }
  828. fCoInit = TRUE;
  829. if (NULL != pServer->pwszParentCAName)
  830. {
  831. // answer file provides both machine and ca names
  832. hr = myFormConfigString(
  833. pServer->pwszParentCAMachine,
  834. pServer->pwszParentCAName,
  835. &pwszConfig);
  836. _JumpIfError(hr, error, "myFormConfigString");
  837. // answer file has complete config string, try to ping it
  838. hr = myPingCertSrv(pwszConfig, NULL, NULL, NULL, NULL, NULL, NULL);
  839. if (S_OK != hr)
  840. {
  841. // can't finish without pingable ca
  842. CSILOG(
  843. hr,
  844. IDS_LOG_PING_PARENT_FAIL,
  845. pwszConfig,
  846. NULL,
  847. NULL);
  848. _JumpErrorStr(hr, error, "myPingCertSrv", pwszConfig);
  849. }
  850. }
  851. else
  852. {
  853. WCHAR *pwszzCAList = NULL;
  854. // answer file only has machine name, try to get ca name
  855. hr = myPingCertSrv(
  856. pServer->pwszParentCAMachine,
  857. NULL,
  858. &pwszzCAList,
  859. NULL,
  860. NULL,
  861. NULL,
  862. NULL);
  863. if (S_OK != hr)
  864. {
  865. // can't finish without pingable ca
  866. CSILOG(
  867. hr,
  868. IDS_LOG_PING_PARENT_FAIL,
  869. pServer->pwszParentCAMachine,
  870. NULL,
  871. NULL);
  872. _JumpErrorStr(hr, error, "myPingCertSrv",
  873. pServer->pwszParentCAMachine);
  874. }
  875. // pick the first one as the choice
  876. pServer->pwszParentCAName = pwszzCAList;
  877. }
  878. }
  879. if (NULL == pServer->pwszRequestFile)
  880. {
  881. // in any case, construct request file name if not defined
  882. hr = BuildRequestFileName(
  883. pServer->pwszCACertFile,
  884. &pServer->pwszRequestFile);
  885. _JumpIfError(hr, error, "BuildRequestFileName");
  886. // make sure in limit
  887. if (MAX_PATH <= wcslen(pServer->pwszRequestFile) + cwcSUFFIXMAX)
  888. {
  889. hr = CO_E_PATHTOOLONG;
  890. CSILOG(
  891. hr,
  892. IDS_LOG_REQUEST_FILE_TOO_LONG,
  893. pServer->pwszRequestFile,
  894. NULL,
  895. NULL);
  896. _JumpErrorStr(hr, error, "Request File", pServer->pwszRequestFile);
  897. }
  898. }
  899. }
  900. // other attributes
  901. if(pServer->fUseDS)
  902. {
  903. pServer->dwRevocationFlags = REVEXT_DEFAULT_DS;
  904. }
  905. else
  906. {
  907. pServer->dwRevocationFlags = REVEXT_DEFAULT_NODS;
  908. }
  909. hr = S_OK;
  910. error:
  911. if (fCoInit)
  912. {
  913. CoUninitialize();
  914. }
  915. if (NULL!=pwszConfig) {
  916. LocalFree(pwszConfig);
  917. }
  918. CSILOG(hr, IDS_LOG_SERVER_UNATTENDED_ATTRIBUTES, NULL, NULL, NULL);
  919. return hr;
  920. }
  921. HRESULT
  922. PrepareClientUnattendedAttributes(
  923. PER_COMPONENT_DATA *pComp)
  924. {
  925. HRESULT hr;
  926. CAWEBCLIENTSETUPINFO *pClient = pComp->CA.pClient;
  927. WCHAR *pwszConfig = NULL;
  928. CAINFO *pCAInfo = NULL;
  929. BOOL fCoInit = FALSE;
  930. WCHAR * pwszDnsName = NULL;
  931. if ((IS_CLIENT_INSTALL & pComp->dwInstallStatus) &&
  932. !(IS_SERVER_INSTALL & pComp->dwInstallStatus))
  933. {
  934. // no extra setting and converting
  935. if (NULL == pClient->pwszWebCAMachine)
  936. {
  937. hr = E_INVALIDARG;
  938. CSILOG(hr, IDS_LOG_CA_MACHINE_REQUIRED, NULL, NULL, NULL);
  939. _JumpError(hr, error, "ca machine name is required");
  940. }
  941. hr = CoInitialize(NULL);
  942. if (S_OK != hr && S_FALSE != hr)
  943. {
  944. _JumpError(hr, error, "CoInitialize");
  945. }
  946. fCoInit = TRUE;
  947. if (NULL == pClient->pwszWebCAName)
  948. {
  949. WCHAR *pwszzCAList = NULL;
  950. // answer file only has machine name, try to get ca name
  951. hr = myPingCertSrv(
  952. pClient->pwszWebCAMachine,
  953. NULL,
  954. &pwszzCAList,
  955. NULL,
  956. NULL,
  957. NULL,
  958. NULL);
  959. if (S_OK != hr)
  960. {
  961. // can't finish without pingable ca
  962. CSILOG(
  963. hr,
  964. IDS_LOG_PING_PARENT_FAIL,
  965. pClient->pwszWebCAMachine,
  966. NULL,
  967. NULL);
  968. _JumpErrorStr(hr, error, "myPingCertSrv",
  969. pClient->pwszWebCAMachine);
  970. }
  971. // pick the first one as the choice
  972. pClient->pwszWebCAName = pwszzCAList;
  973. }
  974. hr = mySanitizeName(pClient->pwszWebCAName, &pClient->pwszSanitizedWebCAName);
  975. _JumpIfError(hr, error, "mySanitizeName");
  976. // build the config string so we can ping the parent CA
  977. hr = myFormConfigString(
  978. pClient->pwszWebCAMachine,
  979. pClient->pwszWebCAName,
  980. &pwszConfig);
  981. _JumpIfError(hr, error, "myFormConfigString");
  982. // ping the CA to retrieve the CA type and DNS name.
  983. hr = myPingCertSrv(pwszConfig, NULL, NULL, NULL, &pCAInfo, NULL, &pwszDnsName);
  984. if (S_OK != hr)
  985. {
  986. // can't finish without pingable ca
  987. CSILOG(
  988. hr,
  989. IDS_LOG_PING_PARENT_FAIL,
  990. pwszConfig,
  991. NULL,
  992. NULL);
  993. _JumpErrorStr(hr, error, "myPingCertSrv", pwszConfig);
  994. }
  995. pClient->WebCAType = pCAInfo->CAType;
  996. // use the FQDN if available
  997. if (NULL!=pwszDnsName) {
  998. LocalFree(pClient->pwszWebCAMachine);
  999. pClient->pwszWebCAMachine=pwszDnsName;
  1000. }
  1001. }
  1002. hr = S_OK;
  1003. error:
  1004. if (NULL!=pwszConfig)
  1005. {
  1006. LocalFree(pwszConfig);
  1007. }
  1008. if (NULL != pCAInfo)
  1009. {
  1010. LocalFree(pCAInfo);
  1011. }
  1012. if (fCoInit)
  1013. {
  1014. CoUninitialize();
  1015. }
  1016. CSILOG(hr, IDS_LOG_CLIENT_UNATTENDED_ATTRIBUTES, NULL, NULL, NULL);
  1017. return hr;
  1018. }
  1019. HRESULT
  1020. PrepareUnattendedAttributes(
  1021. IN HWND hwnd,
  1022. IN WCHAR const *pwszComponent,
  1023. IN WCHAR const *pwszSubComponent,
  1024. IN PER_COMPONENT_DATA *pComp)
  1025. {
  1026. HRESULT hr;
  1027. SUBCOMP *psc = TranslateSubComponent(pwszComponent, pwszSubComponent);
  1028. if (NULL == psc)
  1029. {
  1030. hr = E_INVALIDARG;
  1031. _JumpError(hr, error, "Internal error, unsupported component");
  1032. }
  1033. switch (psc->cscSubComponent)
  1034. {
  1035. case cscServer:
  1036. hr = PrepareServerUnattendedAttributes(hwnd, pComp);
  1037. _JumpIfError(hr, error, "PrepareServerUnattendedAttributes");
  1038. break;
  1039. case cscClient:
  1040. hr = PrepareClientUnattendedAttributes(pComp);
  1041. _JumpIfError(hr, error, "PrepareClientUnattendedAttributes");
  1042. break;
  1043. default:
  1044. hr = E_INVALIDARG;
  1045. _JumpError(hr, error, "Internal error, unsupported component");
  1046. }
  1047. hr = S_OK;
  1048. error:
  1049. return hr;
  1050. }