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.

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