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.

482 lines
14 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: pfximpt.cpp
  8. //
  9. // Contents: PFX import dialog
  10. //
  11. // History: 06/98 xtan
  12. //
  13. //----------------------------------------------------------------------------
  14. #include "pch.cpp"
  15. #pragma hdrstop
  16. #include "cscsp.h"
  17. #include "certmsg.h"
  18. #include "initcert.h"
  19. #include "setuput.h"
  20. #include "cspenum.h"
  21. #include "wizpage.h"
  22. #include "usecert.h"
  23. #define __dwFILE__ __dwFILE_OCMSETUP_PFXIMPT_CPP__
  24. typedef struct _certpfximportinfo
  25. {
  26. HINSTANCE hInstance;
  27. BOOL fUnattended;
  28. WCHAR *pwszFileName;
  29. DWORD dwFileNameSize;
  30. WCHAR *pwszPassword;
  31. DWORD dwPasswordSize;
  32. } CERTPFXIMPORTINFO;
  33. HRESULT
  34. CertBrowsePFX(HINSTANCE hInstance, HWND hDlg)
  35. {
  36. HRESULT hr;
  37. WCHAR *pwszFileNameIn = NULL;
  38. WCHAR *pwszFileNameOut = NULL;
  39. HWND hCtrl = GetDlgItem(hDlg, IDC_PFX_FILENAME);
  40. hr = myUIGetWindowText(hCtrl, &pwszFileNameIn);
  41. _JumpIfError(hr, error, "myUIGetWindowText");
  42. hr = myGetOpenFileName(
  43. hDlg,
  44. hInstance,
  45. IDS_IMPORT_PFX_TITLE,
  46. IDS_PFX_FILE_FILTER,
  47. 0, // no def ext
  48. OFN_PATHMUSTEXIST | OFN_HIDEREADONLY,
  49. pwszFileNameIn,
  50. &pwszFileNameOut);
  51. _JumpIfError(hr, error, "myGetOpenFileName");
  52. if (NULL != pwszFileNameOut)
  53. {
  54. SetWindowText(hCtrl, pwszFileNameOut);
  55. }
  56. hr = S_OK;
  57. error:
  58. if (NULL != pwszFileNameOut)
  59. {
  60. LocalFree(pwszFileNameOut);
  61. }
  62. if (NULL != pwszFileNameIn)
  63. {
  64. LocalFree(pwszFileNameIn);
  65. }
  66. return hr;
  67. }
  68. HRESULT
  69. GetPFXInfo(
  70. HWND hDlg,
  71. CERTPFXIMPORTINFO* pCertPfxImportInfo)
  72. {
  73. HRESULT hr;
  74. GetWindowText(GetDlgItem(hDlg, IDC_PFX_FILENAME),
  75. pCertPfxImportInfo->pwszFileName,
  76. pCertPfxImportInfo->dwFileNameSize);
  77. if (0x0 == pCertPfxImportInfo->pwszFileName[0])
  78. {
  79. // file can't empty
  80. hr = E_INVALIDARG;
  81. CertWarningMessageBox(
  82. pCertPfxImportInfo->hInstance,
  83. pCertPfxImportInfo->fUnattended,
  84. hDlg,
  85. IDS_ERR_EMPTYPFXFILE,
  86. 0,
  87. NULL);
  88. SetFocus(GetDlgItem(hDlg, IDC_PFX_FILENAME));
  89. goto error;
  90. }
  91. GetWindowText(GetDlgItem(hDlg, IDC_PFX_PASSWORD),
  92. pCertPfxImportInfo->pwszPassword,
  93. pCertPfxImportInfo->dwPasswordSize);
  94. hr = S_OK;
  95. error:
  96. return hr;
  97. }
  98. INT_PTR CALLBACK
  99. CertPFXFilePasswordProc(
  100. HWND hDlg,
  101. UINT iMsg,
  102. WPARAM wParam,
  103. LPARAM lParam)
  104. {
  105. HRESULT hr;
  106. BOOL ret = FALSE;
  107. int id = IDCANCEL;
  108. static CERTPFXIMPORTINFO *pCertPfxImportInfo = NULL;
  109. switch (iMsg)
  110. {
  111. case WM_INITDIALOG:
  112. pCertPfxImportInfo = (CERTPFXIMPORTINFO*)lParam;
  113. ret = TRUE;
  114. break;
  115. case WM_COMMAND:
  116. switch (LOWORD(wParam))
  117. {
  118. case IDC_PFX_FILENAME:
  119. break;
  120. case IDC_PFX_PASSWORD:
  121. break;
  122. case IDC_PFX_BROWSE:
  123. CertBrowsePFX(pCertPfxImportInfo->hInstance, hDlg);
  124. ret = TRUE;
  125. break;
  126. case IDOK:
  127. hr = GetPFXInfo(hDlg, pCertPfxImportInfo);
  128. if (S_OK != hr)
  129. {
  130. break;
  131. }
  132. id = IDOK;
  133. case IDCANCEL:
  134. ret = EndDialog(hDlg, id);
  135. break;
  136. }
  137. break;
  138. default:
  139. ret = FALSE;
  140. }
  141. return ret;
  142. }
  143. int
  144. CertGetPFXFileAndPassword(
  145. IN HWND hwnd,
  146. IN HINSTANCE hInstance,
  147. IN BOOL fUnattended,
  148. IN OUT WCHAR *pwszFileName,
  149. IN DWORD dwFileNameSize,
  150. IN OUT WCHAR *pwszPassword,
  151. IN DWORD dwPasswordSize)
  152. {
  153. CERTPFXIMPORTINFO CertPfxImportInfo =
  154. {hInstance, fUnattended,
  155. pwszFileName, dwFileNameSize,
  156. pwszPassword, dwPasswordSize};
  157. return (int) DialogBoxParam(hInstance,
  158. MAKEINTRESOURCE(IDD_PFXIMPORT),
  159. hwnd,
  160. CertPFXFilePasswordProc,
  161. (LPARAM)&CertPfxImportInfo);
  162. }
  163. //--------------------------------------------------------------------
  164. HRESULT
  165. ImportPFXAndUpdateCSPInfo(
  166. IN const HWND hDlg,
  167. IN OUT PER_COMPONENT_DATA *pComp)
  168. {
  169. HRESULT hr;
  170. int nDlgRet;
  171. BOOL bRetVal;
  172. WCHAR wszName[MAX_PATH];
  173. WCHAR wszPassword[MAX_PATH];
  174. CSP_INFO * pCSPInfo;
  175. DWORD dwCSPInfoSize;
  176. CASERVERSETUPINFO * pServer=pComp->CA.pServer;
  177. // variables that must be cleaned up
  178. CRYPT_KEY_PROV_INFO *pCertKeyProvInfo = NULL;
  179. CERT_CONTEXT const *pSavedLeafCert = NULL;
  180. wszName[0] = L'\0';
  181. // get file name & password
  182. if(pComp->fUnattended)
  183. {
  184. CSASSERT(NULL!=pServer->pwszPFXFile);
  185. if(MAX_PATH<=wcslen(pServer->pwszPFXFile)||
  186. NULL!=pServer->pwszPFXPassword &&
  187. MAX_PATH<=wcslen(pServer->pwszPFXPassword))
  188. {
  189. hr = ERROR_BAD_PATHNAME;
  190. CertWarningMessageBox(
  191. pComp->hInstance,
  192. pComp->fUnattended,
  193. hDlg,
  194. IDS_PFX_FILE_OR_PASSWORD_TOO_LONG,
  195. 0,
  196. NULL);
  197. _JumpError(hr, error, "PFX file name or password is too long");
  198. }
  199. wcscpy(wszName, pServer->pwszPFXFile);
  200. wcscpy(wszPassword,
  201. pServer->pwszPFXPassword?pServer->pwszPFXPassword:L"");
  202. if (NULL == pServer->pCSPInfoList)
  203. {
  204. hr = GetCSPInfoList(&pServer->pCSPInfoList);
  205. _JumpIfError(hr, error, "GetCSPInfoList");
  206. }
  207. }
  208. else{
  209. nDlgRet = CertGetPFXFileAndPassword(
  210. hDlg,
  211. pComp->hInstance,
  212. pComp->fUnattended,
  213. wszName,
  214. sizeof(wszName)/sizeof(WCHAR),
  215. wszPassword,
  216. sizeof(wszPassword)/sizeof(WCHAR));
  217. if (IDOK != nDlgRet)
  218. {
  219. // cancel
  220. hr=HRESULT_FROM_WIN32(ERROR_CANCELLED);
  221. _JumpError(hr, error, "CertGetPFXFileAndPassword canceled");
  222. }
  223. }
  224. // import pkcs12
  225. hr=myCertServerImportPFX(
  226. wszName,
  227. wszPassword,
  228. FALSE,
  229. NULL,
  230. NULL,
  231. &pSavedLeafCert);
  232. if (S_OK != hr)
  233. {
  234. if (HRESULT_FROM_WIN32(ERROR_INVALID_PASSWORD)==hr)
  235. {
  236. // tell the user that their password was invalid
  237. CertWarningMessageBox(
  238. pComp->hInstance,
  239. pComp->fUnattended,
  240. hDlg,
  241. IDS_PFX_INVALID_PASSWORD,
  242. 0,
  243. NULL);
  244. _JumpError(hr, error, "myCertServerImportPFX");
  245. }
  246. else if (HRESULT_FROM_WIN32(ERROR_FILE_EXISTS) == hr)
  247. {
  248. if(pComp->fUnattended)
  249. {
  250. nDlgRet=IDYES;
  251. }
  252. else
  253. {
  254. // confirm from user that they want to overwrite
  255. // the existing key and cert
  256. nDlgRet=CertMessageBox(
  257. pComp->hInstance,
  258. pComp->fUnattended,
  259. hDlg,
  260. IDS_PFX_KEYANDCERTEXIST,
  261. 0,
  262. MB_YESNO | MB_ICONWARNING | CMB_NOERRFROMSYS,
  263. NULL);
  264. }
  265. if (IDYES==nDlgRet)
  266. {
  267. hr=myCertServerImportPFX(
  268. wszName,
  269. wszPassword,
  270. TRUE,
  271. NULL,
  272. NULL,
  273. &pSavedLeafCert);
  274. _JumpIfError(hr, errorMsg, "myCertServerImportPFX");
  275. }
  276. else
  277. {
  278. // cancel
  279. hr=HRESULT_FROM_WIN32(ERROR_CANCELLED);
  280. _JumpError(hr, error, "myCertServerImportPFX canceled");
  281. }
  282. }
  283. else if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
  284. {
  285. CertWarningMessageBox(
  286. pComp->hInstance,
  287. pComp->fUnattended,
  288. hDlg,
  289. IDS_PFX_PATH_INVALID,
  290. 0,
  291. wszName);
  292. _JumpError(hr, error, "myCertServerImportPFX");
  293. }
  294. else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  295. {
  296. CertWarningMessageBox(
  297. pComp->hInstance,
  298. pComp->fUnattended,
  299. hDlg,
  300. IDS_PFX_FILE_NOT_FOUND,
  301. 0,
  302. wszName);
  303. _JumpError(hr, error, "myCertServerImportPFX");
  304. }
  305. else if (HRESULT_FROM_WIN32(CRYPT_E_SELF_SIGNED) == hr)
  306. {
  307. // this cert is not appropriate for this CA type (no CA certs found at all)
  308. CertWarningMessageBox(
  309. pComp->hInstance,
  310. pComp->fUnattended,
  311. hDlg,
  312. IDS_PFX_WRONG_SELFSIGN_TYPE,
  313. S_OK, // don't show an error number
  314. NULL);
  315. _JumpError(hr, error, "This cert is not appropriate for this CA type");
  316. }
  317. else
  318. {
  319. // import failed for some other reason
  320. _JumpError(hr, errorMsg, "myCertServerImportPFX");
  321. }
  322. }
  323. // PFX import was successful. The cert is in the machine's MY store.
  324. CSASSERT(NULL!=pSavedLeafCert);
  325. // The following things have been verified by myCertServerImportPFX
  326. // * The cert has an AT_SIGNATURE key
  327. // * The key in the store matches the one on the cer
  328. // * The cert is not expired
  329. //
  330. // We still need to check:
  331. // * self-signed or not
  332. // * verify chain
  333. // Note: IT IS VERY IMPORTANT that pfx import maintains all the
  334. // invariants about CSP, key container, hash, cert validity, etc.
  335. // that the rest of the UI maintains.
  336. // get key prov info from cert
  337. bRetVal=myCertGetCertificateContextProperty(
  338. pSavedLeafCert,
  339. CERT_KEY_PROV_INFO_PROP_ID,
  340. CERTLIB_USE_LOCALALLOC,
  341. (void **)&pCertKeyProvInfo,
  342. &dwCSPInfoSize);
  343. if (FALSE==bRetVal) {
  344. hr=myHLastError();
  345. _JumpError(hr, errorMsg, "myCertGetCertificateContextProperty");
  346. }
  347. // find our description of the CSP
  348. pCSPInfo=findCSPInfoFromList(pServer->pCSPInfoList,
  349. pCertKeyProvInfo->pwszProvName,
  350. pCertKeyProvInfo->dwProvType);
  351. CSASSERT(NULL!=pCSPInfo);
  352. if (pCSPInfo == NULL) // we don't have this CSP enumerated in our UI
  353. {
  354. hr = CRYPT_E_NOT_FOUND;
  355. _JumpError(hr, errorMsg, "pCSPInfo NULL");
  356. }
  357. //
  358. // Looks like this key is good. Use it.
  359. //
  360. // Stop using the previous cert and key
  361. // delete previously created key container, if necessary.
  362. ClearKeyContainerName(pServer);
  363. // update the CSP
  364. // note: CSP, key container, and hash must all be consistent!
  365. pServer->pCSPInfo=pCSPInfo;
  366. hr = DetermineDefaultHash(pServer);
  367. _JumpIfError(hr, error, "DetermineDefaultHash");
  368. // save the name of the key container
  369. hr=SetKeyContainerName(pServer, pCertKeyProvInfo->pwszContainerName);
  370. _JumpIfError(hr, error, "SetKeyContainerName");
  371. // See if we can use the cert
  372. // verify to make sure no cert in chain is revoked, but don't kill yourself if offline
  373. hr=myVerifyCertContext(
  374. pSavedLeafCert,
  375. CA_VERIFY_FLAGS_IGNORE_OFFLINE,
  376. 0,
  377. NULL,
  378. HCCE_LOCAL_MACHINE,
  379. NULL,
  380. NULL);
  381. _JumpIfError(hr, errorMsg, "myVerifyCertContext");
  382. // See if this cert appropriately is self-signed or not.
  383. // A root CA cert must be self-signed, while
  384. // a subordinate CA cert must not be self-signed.
  385. hr=IsCertSelfSignedForCAType(pServer, pSavedLeafCert, &bRetVal);
  386. _JumpIfError(hr, errorMsg, "IsCertSelfSignedForCAType");
  387. if (FALSE==bRetVal) {
  388. // this cert is not appropriate for this CA type
  389. CertWarningMessageBox(
  390. pComp->hInstance,
  391. pComp->fUnattended,
  392. hDlg,
  393. IDS_PFX_WRONG_SELFSIGN_TYPE,
  394. S_OK, // don't show an error number
  395. NULL);
  396. hr=CRYPT_E_SELF_SIGNED;
  397. _JumpError(hr, error, "This cert is not appropriate for this CA type");
  398. }
  399. //
  400. // Looks like this cert is good. Use it.
  401. //
  402. // save the cert and update the hash algorithm
  403. hr=SetExistingCertToUse(pServer, pSavedLeafCert);
  404. _JumpIfError(hr, error, "SetExistingCertToUse");
  405. pSavedLeafCert=NULL;
  406. hr=S_OK;
  407. errorMsg:
  408. if (FAILED(hr)) {
  409. // an error occurred while trying to import the PFX file
  410. CertWarningMessageBox(
  411. pComp->hInstance,
  412. pComp->fUnattended,
  413. hDlg,
  414. IDS_ERR_IMPORTPFX,
  415. hr,
  416. NULL);
  417. }
  418. error:
  419. SecureZeroMemory(wszPassword, wcslen(wszPassword)*sizeof(WCHAR));
  420. CSILOG(
  421. hr,
  422. IDS_LOG_IMPORTPFX,
  423. L'\0' == wszName[0]? NULL : wszName,
  424. NULL,
  425. NULL);
  426. if (NULL != pSavedLeafCert)
  427. {
  428. CertFreeCertificateContext(pSavedLeafCert);
  429. }
  430. if (NULL != pCertKeyProvInfo)
  431. {
  432. LocalFree(pCertKeyProvInfo);
  433. }
  434. return hr;
  435. }