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.

843 lines
29 KiB

  1. /////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2000-2002.
  5. //
  6. // File: TemplateV2RequestPropertyPage.cpp
  7. //
  8. // Contents: Implementation of CTemplateV2RequestPropertyPage
  9. //
  10. //----------------------------------------------------------------------------
  11. // TemplateV2RequestPropertyPage.cpp : implementation file
  12. //
  13. #include "stdafx.h"
  14. #include "TemplateV2RequestPropertyPage.h"
  15. #ifdef _DEBUG
  16. #define new DEBUG_NEW
  17. #undef THIS_FILE
  18. static char THIS_FILE[] = __FILE__;
  19. #endif
  20. /////////////////////////////////////////////////////////////////////////////
  21. // CTemplateV2RequestPropertyPage property page
  22. enum {
  23. REQUEST_PURPOSE_SIGNATURE = 0,
  24. REQUEST_PURPOSE_ENCRYPTION,
  25. REQUEST_PURPOSE_SIGNATURE_AND_ENCRYPTION,
  26. REQUEST_PURPOSE_SIGNATURE_AND_SMARTCARD_LOGON
  27. };
  28. const DWORD CERTTMPL_NON_LOCAL_CSP = (DWORD) -1;
  29. CTemplateV2RequestPropertyPage::CTemplateV2RequestPropertyPage(
  30. CCertTemplate& rCertTemplate, bool& rbIsDirty) :
  31. CHelpPropertyPage(CTemplateV2RequestPropertyPage::IDD),
  32. m_rCertTemplate (rCertTemplate),
  33. m_rbIsDirty (rbIsDirty),
  34. m_nProvDSSCnt (0)
  35. {
  36. _TRACE (1, L"Entering CTemplateV2RequestPropertyPage::CTemplateV2RequestPropertyPage ()\n");
  37. //{{AFX_DATA_INIT(CTemplateV2RequestPropertyPage)
  38. //}}AFX_DATA_INIT
  39. m_rCertTemplate.AddRef ();
  40. _TRACE (-1, L"Leaving CTemplateV2RequestPropertyPage::CTemplateV2RequestPropertyPage ()\n");
  41. }
  42. CTemplateV2RequestPropertyPage::~CTemplateV2RequestPropertyPage()
  43. {
  44. _TRACE (1, L"Entering CTemplateV2RequestPropertyPage::~CTemplateV2RequestPropertyPage ()\n");
  45. while ( !m_CSPList.IsEmpty () )
  46. {
  47. CT_CSP_DATA* pCSPData = m_CSPList.RemoveHead ();
  48. if ( pCSPData )
  49. delete pCSPData;
  50. }
  51. m_rCertTemplate.Release ();
  52. _TRACE (-1, L"Leaving CTemplateV2RequestPropertyPage::~CTemplateV2RequestPropertyPage ()\n");
  53. }
  54. void CTemplateV2RequestPropertyPage::DoDataExchange(CDataExchange* pDX)
  55. {
  56. CHelpPropertyPage::DoDataExchange(pDX);
  57. //{{AFX_DATA_MAP(CTemplateV2RequestPropertyPage)
  58. DDX_Control(pDX, IDC_MINIMUM_KEYSIZE_VALUE, m_minKeySizeCombo);
  59. DDX_Control(pDX, IDC_PURPOSE_COMBO, m_purposeCombo);
  60. //}}AFX_DATA_MAP
  61. }
  62. BEGIN_MESSAGE_MAP(CTemplateV2RequestPropertyPage, CHelpPropertyPage)
  63. //{{AFX_MSG_MAP(CTemplateV2RequestPropertyPage)
  64. ON_CBN_SELCHANGE(IDC_PURPOSE_COMBO, OnSelchangePurposeCombo)
  65. ON_BN_CLICKED(IDC_EXPORT_PRIVATE_KEY, OnExportPrivateKey)
  66. ON_BN_CLICKED(IDC_ARCHIVE_KEY_CHECK, OnArchiveKeyCheck)
  67. ON_BN_CLICKED(IDC_INCLUDE_SYMMETRIC_ALGORITHMS_CHECK, OnIncludeSymmetricAlgorithmsCheck)
  68. ON_CBN_SELCHANGE(IDC_MINIMUM_KEYSIZE_VALUE, OnSelchangeMinimumKeysizeValue)
  69. ON_BN_CLICKED(IDC_DELETE_PERMANENTLY, OnDeletePermanently)
  70. ON_BN_CLICKED(IDC_CSPS, OnCsps)
  71. ON_BN_CLICKED(IDC_ENROLL_WITHOUT_INPUT, OnEnrollWithoutInput)
  72. ON_BN_CLICKED(IDC_ENROLL_PROMPT_USER, OnEnrollPromptUser)
  73. ON_BN_CLICKED(IDC_ENROLL_PROMPT_USER_REQUIRE_IF_PRIVATE_KEY, OnEnrollPromptUserRequireIfPrivateKey)
  74. //}}AFX_MSG_MAP
  75. END_MESSAGE_MAP()
  76. /////////////////////////////////////////////////////////////////////////////
  77. // CTemplateV2RequestPropertyPage message handlers
  78. BOOL CTemplateV2RequestPropertyPage::OnInitDialog()
  79. {
  80. _TRACE (1, L"Entering CTemplateV2RequestPropertyPage::OnInitDialog ()\n");
  81. CHelpPropertyPage::OnInitDialog();
  82. CString text;
  83. VERIFY (text.LoadString (IDS_SIGNATURE));
  84. int nIndex = m_purposeCombo.AddString (text);
  85. if ( nIndex >= 0 )
  86. {
  87. m_purposeCombo.SetItemData (nIndex, (DWORD_PTR) REQUEST_PURPOSE_SIGNATURE);
  88. if ( m_rCertTemplate.HasKeySpecSignature () )
  89. m_purposeCombo.SetCurSel (nIndex);
  90. }
  91. VERIFY (text.LoadString (IDS_ENCRYPTION));
  92. nIndex = m_purposeCombo.AddString (text);
  93. if ( nIndex >= 0 )
  94. {
  95. m_purposeCombo.SetItemData (nIndex, (DWORD_PTR) REQUEST_PURPOSE_ENCRYPTION);
  96. if ( m_rCertTemplate.HasEncryptionSignature () )
  97. m_purposeCombo.SetCurSel (nIndex);
  98. }
  99. VERIFY (text.LoadString (IDS_SIGNATURE_AND_ENCRYPTION));
  100. nIndex = m_purposeCombo.AddString (text);
  101. if ( nIndex >= 0 )
  102. {
  103. // NTRAID# 278356 CertSRV: No CSPs in mmc certificate snapin advanced
  104. // option list with v2 templates that have ENC and SIG as purpose.
  105. bool bHasDigitalSignature = false;
  106. m_rCertTemplate.GetDigitalSignature (bHasDigitalSignature);
  107. m_purposeCombo.SetItemData (nIndex, (DWORD_PTR) REQUEST_PURPOSE_SIGNATURE_AND_ENCRYPTION);
  108. if ( m_rCertTemplate.HasEncryptionSignature () &&
  109. (bHasDigitalSignature || m_rCertTemplate.HasKeySpecSignature ()) )
  110. m_purposeCombo.SetCurSel (nIndex);
  111. }
  112. // NTRAID# 476615 Certtmpl: Signature and Smart Card Logon Certificate
  113. // Purpose should only be available for User Templates.
  114. if ( !m_rCertTemplate.IsMachineType () )
  115. {
  116. VERIFY (text.LoadString (IDS_SIGNATURE_AND_SMARTCARD_LOGON));
  117. nIndex = m_purposeCombo.AddString (text);
  118. if ( nIndex >= 0 )
  119. {
  120. // NTRAID# 278356 CertSRV: No CSPs in mmc certificate snapin advanced
  121. // option list with v2 templates that have ENC and SIG as purpose.
  122. bool bHasDigitalSignature = false;
  123. bool bHasOnlyDigitalSignature = false;
  124. m_rCertTemplate.GetDigitalSignature (bHasDigitalSignature,
  125. &bHasOnlyDigitalSignature);
  126. m_purposeCombo.SetItemData (nIndex, (DWORD_PTR) REQUEST_PURPOSE_SIGNATURE_AND_SMARTCARD_LOGON);
  127. if ( bHasOnlyDigitalSignature &&
  128. bHasDigitalSignature && m_rCertTemplate.HasEncryptionSignature () )
  129. {
  130. m_purposeCombo.SetCurSel (nIndex);
  131. }
  132. }
  133. }
  134. // Initialize minimum key size combo box- values in powers of 2 from 512 to 16384
  135. DWORD dwMinKeySize = 0;
  136. m_rCertTemplate.GetMinimumKeySize (dwMinKeySize);
  137. AddKeySizeToCombo(512, L"512", dwMinKeySize);
  138. AddKeySizeToCombo(768, L"768", dwMinKeySize);
  139. AddKeySizeToCombo(1024, L"1024", dwMinKeySize);
  140. AddKeySizeToCombo(2048, L"2048", dwMinKeySize);
  141. AddKeySizeToCombo(4096, L"4096", dwMinKeySize);
  142. AddKeySizeToCombo(8192, L"8192", dwMinKeySize);
  143. AddKeySizeToCombo(16384, L"16384", dwMinKeySize);
  144. if ( SUCCEEDED (EnumerateCSPs (dwMinKeySize)) )
  145. {
  146. }
  147. if ( m_rCertTemplate.PrivateKeyIsExportable () )
  148. SendDlgItemMessage (IDC_EXPORT_PRIVATE_KEY, BM_SETCHECK, BST_CHECKED);
  149. if ( m_rCertTemplate.AllowPrivateKeyArchival () )
  150. SendDlgItemMessage (IDC_ARCHIVE_KEY_CHECK, BM_SETCHECK, BST_CHECKED);
  151. if ( m_rCertTemplate.IncludeSymmetricAlgorithms () )
  152. SendDlgItemMessage (IDC_INCLUDE_SYMMETRIC_ALGORITHMS_CHECK, BM_SETCHECK, BST_CHECKED);
  153. GetDlgItem (IDC_ARCHIVE_KEY_CHECK)->ShowWindow (SW_SHOW);
  154. GetDlgItem (IDC_MINIMUM_KEYSIZE_VALUE)->ShowWindow (SW_SHOW);
  155. GetDlgItem (IDC_MINIMUM_KEYSIZE_LABEL)->ShowWindow (SW_SHOW);
  156. GetDlgItem (IDC_INCLUDE_SYMMETRIC_ALGORITHMS_CHECK)->ShowWindow (SW_SHOW);
  157. if ( m_rCertTemplate.UserInteractionRequired () )
  158. {
  159. if ( m_rCertTemplate.StrongKeyProtectionRequired () )
  160. SendDlgItemMessage (IDC_ENROLL_PROMPT_USER_REQUIRE_IF_PRIVATE_KEY, BM_SETCHECK, BST_CHECKED);
  161. else
  162. SendDlgItemMessage (IDC_ENROLL_PROMPT_USER, BM_SETCHECK, BST_CHECKED);
  163. }
  164. else
  165. {
  166. SendDlgItemMessage (IDC_ENROLL_WITHOUT_INPUT, BM_SETCHECK, BST_CHECKED);
  167. }
  168. if ( m_rCertTemplate.RemoveInvalidCertFromPersonalStore () )
  169. SendDlgItemMessage (IDC_DELETE_PERMANENTLY, BM_SETCHECK, BST_CHECKED);
  170. EnableControls ();
  171. _TRACE (-1, L"Leaving CTemplateV2RequestPropertyPage::OnInitDialog ()\n");
  172. return TRUE; // return TRUE unless you set the focus to a control
  173. // EXCEPTION: OCX Property Pages should return FALSE
  174. }
  175. void CTemplateV2RequestPropertyPage::EnableControls ()
  176. {
  177. if ( m_rCertTemplate.ReadOnly () )
  178. {
  179. GetDlgItem (IDC_PURPOSE_COMBO)->EnableWindow (FALSE);
  180. GetDlgItem (IDC_EXPORT_PRIVATE_KEY)->EnableWindow (FALSE);
  181. //version 2 fields
  182. GetDlgItem (IDC_ARCHIVE_KEY_CHECK)->EnableWindow (FALSE);
  183. GetDlgItem (IDC_INCLUDE_SYMMETRIC_ALGORITHMS_CHECK)->EnableWindow (FALSE);
  184. SendDlgItemMessage (IDC_INCLUDE_SYMMETRIC_ALGORITHMS_CHECK, BM_SETCHECK, BST_UNCHECKED);
  185. GetDlgItem (IDC_MINIMUM_KEYSIZE_LABEL)->EnableWindow (FALSE);
  186. GetDlgItem (IDC_MINIMUM_KEYSIZE_VALUE)->EnableWindow (FALSE);
  187. GetDlgItem (IDC_DELETE_PERMANENTLY)->EnableWindow (FALSE);
  188. GetDlgItem (IDC_ENROLL_WITHOUT_INPUT)->EnableWindow (FALSE);
  189. GetDlgItem (IDC_ENROLL_PROMPT_USER)->EnableWindow (FALSE);
  190. GetDlgItem (IDC_ENROLL_PROMPT_USER_REQUIRE_IF_PRIVATE_KEY)->EnableWindow (FALSE);
  191. GetDlgItem (IDC_PURPOSE_LABEL)->EnableWindow (FALSE);
  192. GetDlgItem (IDC_INPUT_LABEL)->EnableWindow (FALSE);
  193. GetDlgItem (IDC_CSP_LABEL)->EnableWindow (FALSE);
  194. }
  195. else
  196. {
  197. BOOL bEncryptionSelected = FALSE;
  198. int nIndex = m_purposeCombo.GetCurSel ();
  199. if ( nIndex >= 0 )
  200. {
  201. switch (m_purposeCombo.GetItemData (nIndex))
  202. {
  203. case REQUEST_PURPOSE_SIGNATURE:
  204. GetDlgItem (IDC_ENROLL_WITHOUT_INPUT)->EnableWindow (TRUE);
  205. GetDlgItem (IDC_EXPORT_PRIVATE_KEY)->EnableWindow (TRUE);
  206. bEncryptionSelected = FALSE;
  207. break;
  208. case REQUEST_PURPOSE_SIGNATURE_AND_SMARTCARD_LOGON:
  209. GetDlgItem (IDC_ENROLL_WITHOUT_INPUT)->EnableWindow (FALSE);
  210. GetDlgItem (IDC_EXPORT_PRIVATE_KEY)->EnableWindow (FALSE);
  211. bEncryptionSelected = FALSE;
  212. break;
  213. case REQUEST_PURPOSE_SIGNATURE_AND_ENCRYPTION:
  214. case REQUEST_PURPOSE_ENCRYPTION:
  215. GetDlgItem (IDC_ENROLL_WITHOUT_INPUT)->EnableWindow (TRUE);
  216. GetDlgItem (IDC_EXPORT_PRIVATE_KEY)->EnableWindow (TRUE);
  217. bEncryptionSelected = TRUE;
  218. break;
  219. default:
  220. _ASSERT (0);
  221. break;
  222. }
  223. }
  224. GetDlgItem (IDC_DELETE_PERMANENTLY)->EnableWindow (!bEncryptionSelected);
  225. if ( bEncryptionSelected &&
  226. BST_CHECKED == SendDlgItemMessage (IDC_DELETE_PERMANENTLY, BM_GETCHECK) )
  227. {
  228. SendDlgItemMessage (IDC_DELETE_PERMANENTLY, BM_SETCHECK, BST_UNCHECKED);
  229. m_rCertTemplate.SetRemoveInvalidCertFromPersonalStore (false);
  230. }
  231. GetDlgItem (IDC_INCLUDE_SYMMETRIC_ALGORITHMS_CHECK)->EnableWindow (bEncryptionSelected);
  232. if ( !bEncryptionSelected )
  233. {
  234. SendDlgItemMessage (IDC_INCLUDE_SYMMETRIC_ALGORITHMS_CHECK, BM_SETCHECK, BST_UNCHECKED);
  235. }
  236. BOOL bEnableArchiveKeyCheck = bEncryptionSelected;
  237. if ( m_nProvDSSCnt > 0 )
  238. bEnableArchiveKeyCheck = FALSE;
  239. if ( bEnableArchiveKeyCheck )
  240. {
  241. GetDlgItem (IDC_ARCHIVE_KEY_CHECK)->EnableWindow (TRUE);
  242. }
  243. else
  244. {
  245. SendDlgItemMessage (IDC_ARCHIVE_KEY_CHECK, BM_SETCHECK, BST_UNCHECKED);
  246. OnArchiveKeyCheck (); // clear flag
  247. GetDlgItem (IDC_ARCHIVE_KEY_CHECK)->EnableWindow (FALSE);
  248. }
  249. if ( m_rCertTemplate.IsMachineType () || m_rCertTemplate.SubjectIsCA () ||
  250. m_rCertTemplate.SubjectIsCrossCA () )
  251. {
  252. GetDlgItem (IDC_ENROLL_WITHOUT_INPUT)->EnableWindow (FALSE);
  253. GetDlgItem (IDC_ENROLL_PROMPT_USER)->EnableWindow (FALSE);
  254. GetDlgItem (IDC_ENROLL_PROMPT_USER_REQUIRE_IF_PRIVATE_KEY)->EnableWindow (FALSE);
  255. }
  256. }
  257. }
  258. HRESULT CTemplateV2RequestPropertyPage::EnumerateCSPs(DWORD dwMinKeySize)
  259. {
  260. _TRACE (1, L"Entering CTemplateV2RequestPropertyPage::EnumerateCSPs\n");
  261. HRESULT hr = S_OK;
  262. for (DWORD dwIndex = 0; ;dwIndex++)
  263. {
  264. DWORD cbName = 0;
  265. DWORD dwProvType = 0;
  266. if ( CryptEnumProviders (dwIndex, NULL, 0, &dwProvType, NULL, &cbName) )
  267. {
  268. PWSTR pszTypeName = new WCHAR[cbName];
  269. if ( pszTypeName )
  270. {
  271. if ( CryptEnumProviders (dwIndex, NULL, 0, &dwProvType,
  272. pszTypeName, &cbName) )
  273. {
  274. DWORD dwSigMaxKey = (DWORD) -1;
  275. DWORD dwKeyExMaxKey = (DWORD) -1;
  276. CSPGetMaxKeySupported (pszTypeName, dwProvType, dwSigMaxKey, dwKeyExMaxKey);
  277. // If either of these values is still -1, then it was not
  278. // set. Set to 0.
  279. if ( -1 == dwSigMaxKey )
  280. dwSigMaxKey = 0;
  281. if ( -1 == dwKeyExMaxKey )
  282. dwKeyExMaxKey = 0;
  283. CT_CSP_DATA* pNewData = new CT_CSP_DATA (pszTypeName,
  284. dwProvType, dwSigMaxKey, dwKeyExMaxKey);
  285. if ( pNewData )
  286. {
  287. m_CSPList.AddTail (pNewData);
  288. }
  289. }
  290. else
  291. {
  292. hr = HRESULT_FROM_WIN32 (GetLastError ());
  293. _TRACE (0, L"CryptEnumProviderTypes () failed: 0x%x\n", hr);
  294. break;
  295. }
  296. delete [] pszTypeName;
  297. }
  298. else
  299. hr = E_OUTOFMEMORY;
  300. }
  301. else
  302. {
  303. hr = HRESULT_FROM_WIN32 (GetLastError ());
  304. _TRACE (0, L"CryptEnumProviderTypes () failed: 0x%x\n", hr);
  305. break;
  306. }
  307. }
  308. int nCSPIndex = 0;
  309. CString szCSP;
  310. CString szInvalidCSPs;
  311. // Set the selection
  312. // Get the list of selected CSPs from the cert template.
  313. // If a selected CSP is not found in the generated CSP list, add it to the list
  314. m_nProvDSSCnt = 0;
  315. nCSPIndex = 0;
  316. while ( SUCCEEDED (m_rCertTemplate.GetCSP (nCSPIndex, szCSP)) )
  317. {
  318. bool bFound = false;
  319. for (POSITION nextPos = m_CSPList.GetHeadPosition (); nextPos; )
  320. {
  321. CT_CSP_DATA* pCSPData = m_CSPList.GetNext (nextPos);
  322. if ( pCSPData )
  323. {
  324. if ( !LocaleStrCmp (szCSP, pCSPData->m_szName) )
  325. {
  326. pCSPData->m_bSelected = true;
  327. if ( PROV_DSS == pCSPData->m_dwProvType ||
  328. PROV_DSS_DH == pCSPData->m_dwProvType )
  329. {
  330. m_nProvDSSCnt++;
  331. }
  332. bFound = true;
  333. break;
  334. }
  335. }
  336. }
  337. if ( !bFound )
  338. {
  339. if ( !szInvalidCSPs.IsEmpty () )
  340. szInvalidCSPs += L", ";
  341. szInvalidCSPs += szCSP;
  342. // Should show CSPs that are not available on the client
  343. CT_CSP_DATA* pNewData = new CT_CSP_DATA (szCSP,
  344. CERTTMPL_NON_LOCAL_CSP, 0, 0);
  345. if ( pNewData )
  346. {
  347. pNewData->m_bSelected = true;
  348. m_CSPList.AddTail (pNewData);
  349. }
  350. }
  351. nCSPIndex++;
  352. }
  353. if ( !szInvalidCSPs.IsEmpty () )
  354. {
  355. CString text;
  356. CString caption;
  357. CThemeContextActivator activator;
  358. VERIFY (caption.LoadString (IDS_CERTTMPL));
  359. text.FormatMessage (IDS_CSPS_NOT_INSTALLED_LOCALLY, (PCWSTR) szInvalidCSPs);
  360. MessageBox (text, caption, MB_OK | MB_ICONWARNING);
  361. }
  362. NormalizeCSPList (dwMinKeySize);
  363. EnableControls ();
  364. _TRACE (-1, L"Entering CTemplateV2RequestPropertyPage::EnumerateCSPs: 0x%x\n", hr);
  365. return hr;
  366. }
  367. void CTemplateV2RequestPropertyPage::OnSelchangePurposeCombo()
  368. {
  369. int nIndex = m_purposeCombo.GetCurSel ();
  370. if ( nIndex >= 0 )
  371. {
  372. // NTRAID# 278356 CertSRV: No CSPs in mmc certificate snapin advanced
  373. // option list with v2 templates that have ENC and SIG as purpose.
  374. switch (m_purposeCombo.GetItemData (nIndex))
  375. {
  376. case REQUEST_PURPOSE_SIGNATURE:
  377. m_rCertTemplate.SetEncryptionSignature (false);
  378. m_rCertTemplate.SetKeySpecSignature (true);
  379. m_rCertTemplate.IncludeSymmetricAlgorithms (false);
  380. m_rCertTemplate.AllowPrivateKeyArchival (false);
  381. break;
  382. case REQUEST_PURPOSE_ENCRYPTION:
  383. m_rCertTemplate.SetEncryptionSignature (true);
  384. m_rCertTemplate.SetKeySpecSignature (false);
  385. m_rCertTemplate.SetDigitalSignature (false);
  386. break;
  387. case REQUEST_PURPOSE_SIGNATURE_AND_ENCRYPTION:
  388. m_rCertTemplate.SetEncryptionSignature (true);
  389. m_rCertTemplate.SetKeySpecSignature (false);
  390. m_rCertTemplate.SetDigitalSignature (true);
  391. break;
  392. case REQUEST_PURPOSE_SIGNATURE_AND_SMARTCARD_LOGON:
  393. m_rCertTemplate.SetKeySpecSignature (false);
  394. m_rCertTemplate.SetEncryptionSignature (true);
  395. m_rCertTemplate.SetDigitalSignature (true, true);
  396. // 499389 CertTMPL: Signature and Smartcard Logon purpose does not
  397. // clear CT_FLAG_INCLUDE_SYMMETRIC_ALGORITHMS flag
  398. m_rCertTemplate.IncludeSymmetricAlgorithms (false);
  399. if ( BST_CHECKED == SendDlgItemMessage (IDC_ENROLL_WITHOUT_INPUT, BM_GETCHECK) )
  400. {
  401. m_rCertTemplate.SetUserInteractionRequired (true);
  402. m_rCertTemplate.SetStrongKeyProtectionRequired (false);
  403. SendDlgItemMessage (IDC_ENROLL_WITHOUT_INPUT, BM_SETCHECK, BST_UNCHECKED);
  404. SendDlgItemMessage (IDC_ENROLL_PROMPT_USER, BM_SETCHECK, BST_CHECKED);
  405. }
  406. // smart card keys not exportable
  407. SendDlgItemMessage (IDC_EXPORT_PRIVATE_KEY, BM_SETCHECK, BST_UNCHECKED);
  408. m_rCertTemplate.MakePrivateKeyExportable (false);
  409. break;
  410. default:
  411. _ASSERT (0);
  412. break;
  413. }
  414. }
  415. int nSel = m_minKeySizeCombo.GetCurSel ();
  416. ASSERT (nSel >= 0);
  417. if ( nSel >= 0 )
  418. {
  419. DWORD dwMinKeySize = (DWORD) m_minKeySizeCombo.GetItemData (nSel);
  420. ASSERT (dwMinKeySize > 0);
  421. // Clear CSP list and add only values that correspond, saving
  422. // selection for conforming CSPs
  423. int nInitialSelCnt = GetSelectedCSPCount ();
  424. NormalizeCSPList (dwMinKeySize);
  425. int nFinalSelCnt = GetSelectedCSPCount ();
  426. if ( nInitialSelCnt > 0 && 0 == nFinalSelCnt )
  427. {
  428. CString caption;
  429. CString text;
  430. VERIFY (caption.LoadString (IDS_CSP_SELECTION));
  431. VERIFY (text.LoadString (IDS_NO_SELECTED_CSPS));
  432. if ( IDYES == MessageBox (text, caption, MB_YESNO) )
  433. {
  434. OnCsps();
  435. }
  436. }
  437. }
  438. SetModified ();
  439. m_rbIsDirty = true;
  440. EnableControls ();
  441. }
  442. void CTemplateV2RequestPropertyPage::AddKeySizeToCombo(DWORD dwValue, PCWSTR strValue, DWORD dwSizeToSelect)
  443. {
  444. int nIndex = m_minKeySizeCombo.AddString (strValue);
  445. if ( nIndex >= 0 )
  446. {
  447. m_minKeySizeCombo.SetItemData (nIndex, dwValue);
  448. if ( dwSizeToSelect == dwValue )
  449. m_minKeySizeCombo.SetCurSel (nIndex);
  450. }
  451. }
  452. void CTemplateV2RequestPropertyPage::OnExportPrivateKey()
  453. {
  454. bool bMakeExportable = (BST_CHECKED == SendDlgItemMessage (IDC_EXPORT_PRIVATE_KEY, BM_GETCHECK));
  455. m_rCertTemplate.MakePrivateKeyExportable (bMakeExportable);
  456. SetModified ();
  457. m_rbIsDirty = true;
  458. }
  459. void CTemplateV2RequestPropertyPage::OnArchiveKeyCheck()
  460. {
  461. bool bAllowKeyArchival = (BST_CHECKED == SendDlgItemMessage (IDC_ARCHIVE_KEY_CHECK, BM_GETCHECK));
  462. m_rCertTemplate.AllowPrivateKeyArchival (bAllowKeyArchival);
  463. SetModified ();
  464. m_rbIsDirty = true;
  465. }
  466. void CTemplateV2RequestPropertyPage::OnIncludeSymmetricAlgorithmsCheck()
  467. {
  468. bool bInclude =
  469. (BST_CHECKED == SendDlgItemMessage (IDC_INCLUDE_SYMMETRIC_ALGORITHMS_CHECK, BM_GETCHECK));
  470. m_rCertTemplate.IncludeSymmetricAlgorithms (bInclude);
  471. SetModified ();
  472. m_rbIsDirty = true;
  473. }
  474. void CTemplateV2RequestPropertyPage::OnSelchangeMinimumKeysizeValue()
  475. {
  476. SetModified ();
  477. m_rbIsDirty = true;
  478. int nSel = m_minKeySizeCombo.GetCurSel ();
  479. ASSERT (nSel >= 0);
  480. if ( nSel >= 0 )
  481. {
  482. DWORD dwMinKeySize = (DWORD) m_minKeySizeCombo.GetItemData (nSel);
  483. ASSERT (dwMinKeySize > 0);
  484. HRESULT hr = m_rCertTemplate.SetMinimumKeySizeValue (dwMinKeySize);
  485. if ( FAILED (hr) )
  486. {
  487. CString text;
  488. CString caption;
  489. CThemeContextActivator activator;
  490. VERIFY (caption.LoadString (IDS_CERTTMPL));
  491. // security review 2/20/2002 BryanWal ok
  492. text.FormatMessage (IDS_CANNOT_WRITE_MINKEYSIZE, hr);
  493. MessageBox (text, caption, MB_OK | MB_ICONWARNING);
  494. }
  495. // Clear CSP list and add only values that correspond, saving checks
  496. int nInitialSelCnt = GetSelectedCSPCount ();
  497. NormalizeCSPList (dwMinKeySize);
  498. int nFinalSelCnt = GetSelectedCSPCount ();
  499. if ( nInitialSelCnt > 0 && 0 == nFinalSelCnt )
  500. {
  501. CString caption;
  502. CString text;
  503. VERIFY (caption.LoadString (IDS_CSP_SELECTION));
  504. VERIFY (text.LoadString (IDS_NO_SELECTED_CSPS));
  505. if ( IDYES == MessageBox (text, caption, MB_YESNO) )
  506. {
  507. OnCsps();
  508. }
  509. }
  510. }
  511. }
  512. void CTemplateV2RequestPropertyPage::DoContextHelp (HWND hWndControl)
  513. {
  514. _TRACE(1, L"Entering CTemplateV2RequestPropertyPage::DoContextHelp\n");
  515. switch (::GetDlgCtrlID (hWndControl))
  516. {
  517. case IDC_STATIC:
  518. case IDC_MINIMUM_KEYSIZE_LABEL:
  519. case IDC_INPUT_LABEL:
  520. break;
  521. default:
  522. // Display context help for a control
  523. if ( !::WinHelp (
  524. hWndControl,
  525. GetContextHelpFile (),
  526. HELP_WM_HELP,
  527. (DWORD_PTR) g_aHelpIDs_IDD_TEMPLATE_V2_REQUEST) )
  528. {
  529. _TRACE(0, L"WinHelp () failed: 0x%x\n", GetLastError ());
  530. }
  531. break;
  532. }
  533. _TRACE(-1, L"Leaving CTemplateV2RequestPropertyPage::DoContextHelp\n");
  534. }
  535. void CTemplateV2RequestPropertyPage::OnDeletePermanently()
  536. {
  537. m_rCertTemplate.SetRemoveInvalidCertFromPersonalStore (
  538. BST_CHECKED == SendDlgItemMessage (IDC_DELETE_PERMANENTLY, BM_GETCHECK));
  539. SetModified ();
  540. m_rbIsDirty = true;
  541. }
  542. HRESULT CTemplateV2RequestPropertyPage::CSPGetMaxKeySupported (
  543. PCWSTR pszProvider,
  544. DWORD dwProvType,
  545. DWORD& rdwSigMaxKey,
  546. DWORD& rdwKeyExMaxKey)
  547. {
  548. _TRACE (1, L"Entering CTemplateV2RequestPropertyPage::CSPGetMaxKeySupported (%s)\n",
  549. pszProvider);
  550. HRESULT hr = S_OK;
  551. HCRYPTPROV hProv = 0;
  552. BOOL bResult = ::CryptAcquireContext (&hProv,
  553. NULL,
  554. pszProvider,
  555. dwProvType,
  556. CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
  557. if ( bResult )
  558. {
  559. PROV_ENUMALGS_EX EnumAlgs; // Structure to hold information on
  560. // a supported algorithm
  561. DWORD dFlag = CRYPT_FIRST; // Flag indicating that the first
  562. // supported algorithm is to be
  563. // enumerated. Changed to 0 after the
  564. // first call to the function.
  565. DWORD cbData = sizeof(PROV_ENUMALGS_EX);
  566. while (CryptGetProvParam(
  567. hProv, // handle to an open cryptographic provider
  568. PP_ENUMALGS_EX,
  569. (BYTE *)&EnumAlgs, // information on the next algorithm
  570. &cbData, // number of bytes in the PROV_ENUMALGS_EX
  571. dFlag)) // flag to indicate whether this is a first or
  572. // subsequent algorithm supported by the
  573. // CSP.
  574. {
  575. if ( ALG_CLASS_SIGNATURE == GET_ALG_CLASS (EnumAlgs.aiAlgid) )
  576. rdwSigMaxKey = EnumAlgs.dwMaxLen;
  577. if ( ALG_CLASS_KEY_EXCHANGE == GET_ALG_CLASS (EnumAlgs.aiAlgid) )
  578. rdwKeyExMaxKey = EnumAlgs.dwMaxLen;
  579. if ( -1 != rdwSigMaxKey && -1 != rdwKeyExMaxKey )
  580. break; // both have been set
  581. dFlag = 0; // Set to 0 after the first call,
  582. } // end of while loop. When all of the supported algorithms have
  583. // been enumerated, the function returns FALSE.
  584. ::CryptReleaseContext (hProv, 0);
  585. }
  586. else
  587. {
  588. DWORD dwErr = GetLastError ();
  589. _TRACE (0, L"CryptAcquireContext () failed: 0x%x\n", dwErr);
  590. hr = HRESULT_FROM_WIN32 (dwErr);
  591. }
  592. _TRACE (-1, L"Leaving CTemplateV2RequestPropertyPage::CSPGetMaxKeySupported (%s)\n",
  593. pszProvider);
  594. return hr;
  595. }
  596. // NTRAID# 313348 Cert Template UI: Need to warn the user if the template
  597. // minimum key length is not supported by the CSPs
  598. void CTemplateV2RequestPropertyPage::NormalizeCSPList (DWORD dwMinKeySize)
  599. {
  600. bool bSignatureOnly = false;
  601. int nIndex = m_purposeCombo.GetCurSel ();
  602. if ( nIndex >= 0 )
  603. bSignatureOnly = (REQUEST_PURPOSE_SIGNATURE == m_purposeCombo.GetItemData (nIndex));
  604. // Check for conforming CSPs
  605. for (POSITION nextPos = m_CSPList.GetHeadPosition (); nextPos; )
  606. {
  607. CT_CSP_DATA* pCSPData = m_CSPList.GetNext (nextPos);
  608. if ( pCSPData )
  609. {
  610. bool bAddString = false;
  611. // NTRAID# 460671: Certtmpl.msc: Should show CSPs that is not
  612. // available on the client
  613. if ( CERTTMPL_NON_LOCAL_CSP == pCSPData->m_dwProvType )
  614. bAddString = true;
  615. else if ( bSignatureOnly && pCSPData->m_dwSigMaxKeySize >= dwMinKeySize )
  616. bAddString = true;
  617. else if ( pCSPData->m_dwKeyExMaxKeySize >= dwMinKeySize )
  618. bAddString = true;
  619. if ( bAddString )
  620. {
  621. pCSPData->m_bConforming = true;
  622. }
  623. else
  624. {
  625. pCSPData->m_bConforming = false;
  626. if ( pCSPData->m_bSelected )
  627. {
  628. HRESULT hr = m_rCertTemplate.ModifyCSPList (pCSPData->m_szName, false); // remove
  629. if ( SUCCEEDED (hr) )
  630. {
  631. pCSPData->m_bSelected = false;
  632. if ( PROV_DSS == pCSPData->m_dwProvType ||
  633. PROV_DSS_DH == pCSPData->m_dwProvType )
  634. {
  635. m_nProvDSSCnt--;
  636. }
  637. SetModified ();
  638. m_rbIsDirty = true;
  639. }
  640. }
  641. }
  642. }
  643. }
  644. }
  645. int CTemplateV2RequestPropertyPage::GetSelectedCSPCount ()
  646. {
  647. int nSelected = 0;
  648. for (POSITION nextPos = m_CSPList.GetHeadPosition (); nextPos; )
  649. {
  650. CT_CSP_DATA* pCSPData = m_CSPList.GetNext (nextPos);
  651. if ( pCSPData )
  652. {
  653. if ( pCSPData->m_bSelected )
  654. nSelected++;
  655. }
  656. }
  657. return nSelected;
  658. }
  659. void CTemplateV2RequestPropertyPage::OnCsps()
  660. {
  661. bool bSignatureOnly = false;
  662. int nIndex = m_purposeCombo.GetCurSel ();
  663. if ( nIndex >= 0 )
  664. bSignatureOnly = (REQUEST_PURPOSE_SIGNATURE == m_purposeCombo.GetItemData (nIndex));
  665. CSelectCSPDlg dlg (this, m_rCertTemplate, m_CSPList, m_nProvDSSCnt);
  666. if ( IDOK == dlg.DoModal () )
  667. {
  668. HRESULT hr = S_OK;
  669. for (POSITION nextPos = m_CSPList.GetHeadPosition (); nextPos; )
  670. {
  671. CT_CSP_DATA* pCSPData = m_CSPList.GetNext (nextPos);
  672. if ( pCSPData )
  673. {
  674. if ( pCSPData->m_bSelected )
  675. hr = m_rCertTemplate.ModifyCSPList (pCSPData->m_szName, true); // add
  676. else
  677. hr = m_rCertTemplate.ModifyCSPList (pCSPData->m_szName, false); // remove
  678. if ( FAILED (hr) )
  679. break;
  680. }
  681. }
  682. if ( SUCCEEDED (hr) )
  683. {
  684. SetModified ();
  685. m_rbIsDirty = true;
  686. }
  687. EnableControls ();
  688. }
  689. }
  690. void CTemplateV2RequestPropertyPage::OnEnrollWithoutInput()
  691. {
  692. m_rCertTemplate.SetUserInteractionRequired (false);
  693. m_rCertTemplate.SetStrongKeyProtectionRequired (false);
  694. SetModified ();
  695. m_rbIsDirty = true;
  696. }
  697. void CTemplateV2RequestPropertyPage::OnEnrollPromptUser()
  698. {
  699. m_rCertTemplate.SetUserInteractionRequired (true);
  700. m_rCertTemplate.SetStrongKeyProtectionRequired (false);
  701. SetModified ();
  702. m_rbIsDirty = true;
  703. }
  704. void CTemplateV2RequestPropertyPage::OnEnrollPromptUserRequireIfPrivateKey()
  705. {
  706. m_rCertTemplate.SetUserInteractionRequired (true);
  707. m_rCertTemplate.SetStrongKeyProtectionRequired (true);
  708. SetModified ();
  709. m_rbIsDirty = true;
  710. }