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.

1336 lines
29 KiB

  1. /*++
  2. Copyright (c) 1994-2001 Microsoft Corporation
  3. Module Name :
  4. authent.cpp
  5. Abstract:
  6. WWW Authentication Dialog
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Sergei Antonov (sergeia)
  10. Project:
  11. Internet Services Manager
  12. Revision History:
  13. --*/
  14. #include "stdafx.h"
  15. #include "resource.h"
  16. #include "common.h"
  17. #include "inetprop.h"
  18. //#include "supdlgs.h"
  19. #include "w3sht.h"
  20. #include "wincrypt.h"
  21. #include "cryptui.h"
  22. #include "certmap.h"
  23. //#include "basdom.h"
  24. #include "anondlg.h"
  25. #include "seccom.h"
  26. #ifdef _DEBUG
  27. #define new DEBUG_NEW
  28. #undef THIS_FILE
  29. static char THIS_FILE[] = __FILE__;
  30. #endif
  31. const LPCTSTR SZ_CTL_DEFAULT_STORE_NAME = _T("CA");
  32. const LPCSTR szOID_IIS_VIRTUAL_SERVER = "1.3.6.1.4.1.311.30.1";
  33. //
  34. // Needed for GetModuleFileName() below:
  35. //
  36. extern HINSTANCE hInstance;
  37. CSecCommDlg::CSecCommDlg(
  38. IN LPCTSTR lpstrServerName,
  39. IN LPCTSTR lpstrMetaPath,
  40. IN CString & strBasicDomain,
  41. IN DWORD & dwAuthFlags,
  42. IN CComAuthInfo * pAuthInfo,
  43. IN DWORD & dwAccessPermissions,
  44. IN BOOL fIsMasterInstance,
  45. IN BOOL fSSLSupported,
  46. IN BOOL fSSL128Supported,
  47. IN BOOL fU2Installed,
  48. IN CString & strCTLIdentifier,
  49. IN CString & strCTLStoreName,
  50. IN BOOL fEditCTLs,
  51. IN BOOL fIsLocal,
  52. IN CWnd * pParent OPTIONAL
  53. )
  54. /*++
  55. Routine Description:
  56. Authentication dialog constructor
  57. Arguments:
  58. LPCTSTR lpstrServerName : Server name
  59. LPCTSTR lpstrMetaPath : Metabase path
  60. CString & strBasicDomain : Basic domain name
  61. DWORD & dwAuthFlags : Authorization flags
  62. DWORD & dwAccessPermissions : Access permissions
  63. BOOL fIsMasterInstance : Master instance
  64. BOOL fSSLSupported : TRUE if SSL is supported
  65. BOOL fSSL128Supported : TRUE if 128 bit SSL is supported
  66. CString & strCTLIdentifier
  67. CString & strCTLStoreName
  68. BOOL fEditCTLs
  69. BOOL fIsLocal
  70. CWnd * pParent : Optional parent window
  71. Return Value:
  72. N/A
  73. --*/
  74. : CDialog(CSecCommDlg::IDD, pParent),
  75. m_strServerName(lpstrServerName),
  76. m_strMetaPath(lpstrMetaPath),
  77. m_dwAuthFlags(dwAuthFlags),
  78. m_pAuthInfo(pAuthInfo),
  79. m_dwAccessPermissions(dwAccessPermissions),
  80. m_fIsMasterInstance(fIsMasterInstance),
  81. m_fSSLEnabledOnServer(FALSE),
  82. m_fSSLInstalledOnServer(FALSE),
  83. m_fSSL128Supported(fSSL128Supported),
  84. m_fU2Installed(fU2Installed),
  85. m_hCTLStore(NULL),
  86. m_bCTLDirty(FALSE),
  87. m_iLastUsedCert(-1),
  88. m_fIsLocal(fIsLocal),
  89. m_fEditCTLs(fEditCTLs)
  90. {
  91. #if 0 // Keep Class Wizard happy
  92. //{{AFX_DATA_INIT(CSecCommDlg)
  93. m_nRadioNoCert = -1;
  94. m_fAccountMapping = FALSE;
  95. //m_fEnableDS = FALSE;
  96. m_fRequireSSL = FALSE;
  97. m_fEnableCtl = FALSE;
  98. m_strCtl = _T("");
  99. //}}AFX_DATA_INIT
  100. #endif // 0
  101. if (fSSLSupported)
  102. {
  103. ::IsSSLEnabledOnServer(
  104. m_pAuthInfo,
  105. m_fSSLInstalledOnServer,
  106. m_fSSLEnabledOnServer
  107. );
  108. }
  109. else
  110. {
  111. m_fSSLInstalledOnServer = m_fSSLEnabledOnServer = FALSE;
  112. }
  113. if (IS_FLAG_SET(m_dwAccessPermissions, MD_ACCESS_REQUIRE_CERT))
  114. {
  115. m_nRadioNoCert = RADIO_REQ_CERT;
  116. }
  117. else if (IS_FLAG_SET(m_dwAccessPermissions, MD_ACCESS_NEGO_CERT))
  118. {
  119. m_nRadioNoCert = RADIO_ACCEPT_CERT;
  120. }
  121. else
  122. {
  123. m_nRadioNoCert = RADIO_NO_CERT;
  124. }
  125. m_fRequireSSL = m_fSSLInstalledOnServer
  126. && IS_FLAG_SET(m_dwAccessPermissions, MD_ACCESS_SSL);
  127. m_fRequire128BitSSL = m_fSSLInstalledOnServer
  128. && IS_FLAG_SET(m_dwAccessPermissions, MD_ACCESS_SSL128);
  129. m_fAccountMapping = m_fSSLInstalledOnServer
  130. && IS_FLAG_SET(m_dwAccessPermissions, MD_ACCESS_MAP_CERT);
  131. //
  132. // CTL information.
  133. //
  134. if (fEditCTLs)
  135. {
  136. m_strCTLIdentifier = strCTLIdentifier;
  137. m_strCTLStoreName = strCTLStoreName;
  138. if (m_strCTLStoreName.IsEmpty())
  139. {
  140. m_strCTLStoreName = SZ_CTL_DEFAULT_STORE_NAME;
  141. }
  142. m_strCtl.Empty();
  143. m_fEnableCtl = !m_strCTLIdentifier.IsEmpty()
  144. && !strCTLStoreName.IsEmpty();
  145. //
  146. // For now, we only allow enabling when editing the local machine
  147. //
  148. m_fEnableCtl &= m_fIsLocal;
  149. }
  150. else
  151. {
  152. m_fEnableCtl = FALSE;
  153. m_check_EnableCtl.EnableWindow(FALSE);
  154. }
  155. }
  156. CSecCommDlg::~CSecCommDlg()
  157. /*++
  158. Routine Description:
  159. custom destructor for CSecCommDlg
  160. Arguments:
  161. None
  162. Return Value:
  163. None
  164. --*/
  165. {
  166. // dereference the CTL context pointers in the combo box
  167. //CleanUpCTLList();
  168. }
  169. void
  170. CSecCommDlg::DoDataExchange(
  171. IN CDataExchange * pDX
  172. )
  173. /*++
  174. Routine Description:
  175. Initialise/Store control data
  176. Arguments:
  177. CDataExchange * pDX - DDX/DDV control structure
  178. Return Value:
  179. None
  180. --*/
  181. {
  182. CDialog::DoDataExchange(pDX);
  183. //{{AFX_DATA_MAP(CSecCommDlg)
  184. DDX_Radio(pDX, IDC_RADIO_NO_CERT, m_nRadioNoCert);
  185. DDX_Check(pDX, IDC_CHECK_SSL_ACCOUNT_MAPPING, m_fAccountMapping);
  186. DDX_Check(pDX, IDC_CHECK_REQUIRE_SSL, m_fRequireSSL);
  187. DDX_Check(pDX, IDC_CHECK_REQUIRE_128BIT, m_fRequire128BitSSL);
  188. DDX_Check(pDX, IDC_CHECK_ENABLE_CTL, m_fEnableCtl);
  189. DDX_CBString(pDX, IDC_COMBO_CTL, m_strCtl);
  190. DDX_Control(pDX, IDC_CTL_SEPERATOR, m_static_CTLSeparator);
  191. DDX_Control(pDX, IDC_STATIC_CURRENT_CTL, m_static_CTLPrompt);
  192. DDX_Control(pDX, IDC_CHECK_SSL_ACCOUNT_MAPPING, m_check_AccountMapping);
  193. DDX_Control(pDX, IDC_CHECK_REQUIRE_SSL, m_check_RequireSSL);
  194. DDX_Control(pDX, IDC_CHECK_REQUIRE_128BIT, m_check_Require128BitSSL);
  195. DDX_Control(pDX, IDC_CHECK_ENABLE_CTL, m_check_EnableCtl);
  196. DDX_Control(pDX, IDC_BUTTON_EDIT_CTL, m_button_EditCtl);
  197. DDX_Control(pDX, IDC_BUTTON_NEW_CTL, m_button_NewCtl);
  198. DDX_Control(pDX, IDC_CERTMAPCTRL1, m_ocx_ClientMappings);
  199. DDX_Control(pDX, IDC_COMBO_CTL, m_combo_ctl);
  200. //}}AFX_DATA_MAP
  201. //
  202. // Private DDX Controls
  203. //
  204. DDX_Control(pDX, IDC_RADIO_REQUIRE_CERT, m_radio_RequireCert);
  205. DDX_Control(pDX, IDC_RADIO_ACCEPT_CERT, m_radio_AcceptCert);
  206. }
  207. //
  208. // Message Map
  209. //
  210. BEGIN_MESSAGE_MAP(CSecCommDlg, CDialog)
  211. //{{AFX_MSG_MAP(CSecCommDlg)
  212. ON_BN_CLICKED(IDC_CHECK_SSL_ACCOUNT_MAPPING, OnCheckSslAccountMapping)
  213. ON_BN_CLICKED(IDC_CHECK_REQUIRE_SSL, OnCheckRequireSsl)
  214. ON_BN_CLICKED(IDC_RADIO_ACCEPT_CERT, OnRadioAcceptCert)
  215. ON_BN_CLICKED(IDC_RADIO_NO_CERT, OnRadioNoCert)
  216. ON_BN_CLICKED(IDC_RADIO_REQUIRE_CERT, OnRadioRequireCert)
  217. ON_BN_CLICKED(IDC_BUTTON_EDIT_CTL, OnButtonEditCtl)
  218. ON_BN_CLICKED(IDC_CHECK_ENABLE_CTL, OnCheckEnableCtl)
  219. ON_BN_CLICKED(IDC_BUTTON_NEW_CTL, OnButtonNewCtl)
  220. ON_CBN_SELCHANGE(IDC_COMBO_CTL, OnSelchangeComboCtl)
  221. ON_WM_DESTROY()
  222. //}}AFX_MSG_MAP
  223. END_MESSAGE_MAP()
  224. void
  225. CSecCommDlg::SetControlStates()
  226. /*++
  227. Routine Description:
  228. Set control states depending on current data in the dialog
  229. Arguments:
  230. None
  231. Return Value:
  232. None
  233. --*/
  234. {
  235. m_check_RequireSSL.EnableWindow(m_fSSLEnabledOnServer);
  236. m_check_Require128BitSSL.EnableWindow(
  237. m_fSSLEnabledOnServer
  238. && m_fSSL128Supported
  239. && m_fRequireSSL
  240. );
  241. m_ocx_ClientMappings.EnableWindow(
  242. m_fAccountMapping
  243. && !m_fU2Installed
  244. && !m_fIsMasterInstance
  245. );
  246. m_radio_RequireCert.EnableWindow(m_fRequireSSL);
  247. //
  248. // Special case: if "require SSL" is off, but "require
  249. // client certificates" is on, change the latter to "accept
  250. // client certificates"
  251. //
  252. if (m_radio_RequireCert.GetCheck() > 0 && !m_fRequireSSL)
  253. {
  254. m_radio_RequireCert.SetCheck(0);
  255. m_radio_AcceptCert.SetCheck(1);
  256. m_nRadioNoCert = RADIO_ACCEPT_CERT;
  257. }
  258. if (m_fEditCTLs)
  259. {
  260. m_static_CTLPrompt.EnableWindow(m_fEnableCtl);
  261. m_combo_ctl.EnableWindow(m_fEnableCtl);
  262. m_button_EditCtl.EnableWindow(m_fEnableCtl);
  263. m_button_NewCtl.EnableWindow(m_fEnableCtl);
  264. m_ocx_CertificateAuthorities.EnableWindow(m_fEnableCtl);
  265. //
  266. // If enable Ctl is on, but nothing is selected, disable Edit
  267. //
  268. if (m_fEnableCtl)
  269. {
  270. if (m_combo_ctl.GetCurSel() == CB_ERR)
  271. {
  272. m_button_EditCtl.EnableWindow(FALSE);
  273. }
  274. }
  275. }
  276. else
  277. {
  278. m_fEnableCtl = FALSE;
  279. //
  280. // Hide the controls
  281. //
  282. DeActivateControl(m_static_CTLPrompt);
  283. DeActivateControl(m_combo_ctl);
  284. DeActivateControl(m_button_EditCtl);
  285. DeActivateControl(m_button_NewCtl);
  286. DeActivateControl(m_ocx_CertificateAuthorities);
  287. DeActivateControl(m_check_EnableCtl);
  288. DeActivateControl(m_static_CTLSeparator);
  289. }
  290. }
  291. //
  292. // Message Handlers
  293. //
  294. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  295. BOOL
  296. CSecCommDlg::OnInitDialog()
  297. /*++
  298. Routine Description:
  299. WM_INITDIALOG handler. Initialize the dialog.
  300. Arguments:
  301. None.
  302. Return Value:
  303. TRUE if no focus is to be set automatically, FALSE if the focus
  304. is already set.
  305. --*/
  306. {
  307. CDialog::OnInitDialog();
  308. //
  309. // Initialize certificate authorities ocx
  310. //
  311. CRect rc(0, 0, 0, 0);
  312. m_ocx_CertificateAuthorities.Create(
  313. _T("CertWiz"),
  314. WS_BORDER,
  315. rc,
  316. this,
  317. IDC_APPSCTRL
  318. );
  319. CString strCaption;
  320. VERIFY(strCaption.LoadString(IDS_OCX_CERTMAP));
  321. m_ocx_ClientMappings.SetCaption(strCaption);
  322. m_ocx_ClientMappings.SetServerInstance(m_strMetaPath);
  323. m_ocx_ClientMappings.SetMachineName(m_strServerName);
  324. //
  325. // Initialize the CTL list data
  326. //
  327. InitializeCTLList();
  328. SetControlStates();
  329. return TRUE;
  330. }
  331. void
  332. CSecCommDlg::OnCheckSslAccountMapping()
  333. /*++
  334. Routine Description:
  335. SSL Account mapping checkbox handler
  336. Arguments:
  337. None
  338. Return Value:
  339. None
  340. --*/
  341. {
  342. m_fAccountMapping = !m_fAccountMapping;
  343. SetControlStates();
  344. }
  345. void
  346. CSecCommDlg::OnOK()
  347. /*++
  348. Routine Description:
  349. OK button handler, save information
  350. Arguments:
  351. None
  352. Return Value:
  353. None
  354. --*/
  355. {
  356. if (UpdateData(TRUE))
  357. {
  358. SET_FLAG_IF(m_fAccountMapping, m_dwAccessPermissions, MD_ACCESS_MAP_CERT);
  359. SET_FLAG_IF(m_fRequireSSL, m_dwAccessPermissions, MD_ACCESS_SSL);
  360. SET_FLAG_IF(m_fRequire128BitSSL, m_dwAccessPermissions, MD_ACCESS_SSL128);
  361. RESET_FLAG(m_dwAccessPermissions,
  362. (MD_ACCESS_REQUIRE_CERT | MD_ACCESS_NEGO_CERT));
  363. switch(m_nRadioNoCert)
  364. {
  365. case RADIO_REQ_CERT:
  366. SET_FLAG(m_dwAccessPermissions,
  367. (MD_ACCESS_REQUIRE_CERT | MD_ACCESS_NEGO_CERT));
  368. break;
  369. case RADIO_ACCEPT_CERT:
  370. SET_FLAG(m_dwAccessPermissions, MD_ACCESS_NEGO_CERT);
  371. break;
  372. }
  373. //
  374. // Provide warning if no authentication is selected
  375. //
  376. if (!m_dwAuthFlags && !m_dwAccessPermissions
  377. && !NoYesMessageBox(IDS_WRN_NO_AUTH))
  378. {
  379. //
  380. // Don't dismiss the dialog
  381. //
  382. return;
  383. }
  384. //
  385. // If CTL stuff has changed, update the strings
  386. //
  387. if (m_bCTLDirty)
  388. {
  389. //
  390. // Get the index of the selected item
  391. //
  392. INT iSel = m_combo_ctl.GetCurSel();
  393. //
  394. // If nothing is selected, then clear out the strings
  395. //
  396. if (!m_fEnableCtl || (iSel == CB_ERR))
  397. {
  398. m_strCTLIdentifier.Empty();
  399. m_strCTLStoreName.Empty();
  400. }
  401. else
  402. {
  403. //
  404. // There is one selected. Update the Identifier string
  405. // first get the context itself
  406. //
  407. PCCTL_CONTEXT pCTL =
  408. (PCCTL_CONTEXT)m_combo_ctl.GetItemData(iSel);
  409. if (pCTL != NULL)
  410. {
  411. //
  412. // Now get the list identifier for it and put it in
  413. // the string the list identifier is a inherint value
  414. // of the context and doesn't need to be read in seperately.
  415. // We can just reference it.
  416. //
  417. m_strCTLIdentifier.Empty();
  418. if (pCTL->pCtlInfo
  419. && pCTL->pCtlInfo->ListIdentifier.cbData >= 2
  420. && pCTL->pCtlInfo->ListIdentifier.cbData)
  421. {
  422. //
  423. // If the identifiers are the same, then this is
  424. // our default CTL
  425. //
  426. // m_strCTLIdentifier =
  427. // (PWCHAR)pCTL->pCtlInfo->ListIdentifier.pbData;
  428. wcsncpy(m_strCTLIdentifier.GetBuffer(
  429. pCTL->pCtlInfo->ListIdentifier.cbData + 2),
  430. (PWCHAR)pCTL->pCtlInfo->ListIdentifier.pbData,
  431. pCTL->pCtlInfo->ListIdentifier.cbData
  432. );
  433. m_strCTLIdentifier.ReleaseBuffer();
  434. }
  435. }
  436. else
  437. {
  438. m_strCTLIdentifier.Empty();
  439. m_strCTLStoreName.Empty();
  440. }
  441. }
  442. }
  443. CDialog::OnOK();
  444. }
  445. }
  446. void
  447. CSecCommDlg::OnCheckRequireSsl()
  448. /*++
  449. Routine Description:
  450. 'require ssl' checkbox handler
  451. Arguments:
  452. None
  453. Return Value:
  454. None
  455. --*/
  456. {
  457. m_fRequireSSL = !m_fRequireSSL;
  458. if (!m_fRequireSSL)
  459. {
  460. if (BST_CHECKED == m_check_Require128BitSSL.GetCheck())
  461. {
  462. m_check_Require128BitSSL.SetCheck(BST_UNCHECKED);
  463. }
  464. }
  465. SetControlStates();
  466. }
  467. void
  468. CSecCommDlg::OnRadioNoCert()
  469. /*++
  470. Routine Description:
  471. 'Do not accept certificates' radio button handler
  472. Arguments:
  473. None
  474. Return Value:
  475. None
  476. --*/
  477. {
  478. m_nRadioNoCert = RADIO_NO_CERT;
  479. SetControlStates();
  480. }
  481. void
  482. CSecCommDlg::OnRadioAcceptCert()
  483. /*++
  484. Routine Description:
  485. 'accept certificates' radio button handler
  486. Arguments:
  487. None
  488. Return Value:
  489. None
  490. --*/
  491. {
  492. m_nRadioNoCert = RADIO_ACCEPT_CERT;
  493. SetControlStates();
  494. }
  495. void
  496. CSecCommDlg::OnRadioRequireCert()
  497. /*++
  498. Routine Description:
  499. 'require certificates' radio button handler
  500. Arguments:
  501. None
  502. Return Value:
  503. None
  504. --*/
  505. {
  506. m_nRadioNoCert = RADIO_REQ_CERT;
  507. SetControlStates();
  508. }
  509. void
  510. CSecCommDlg::OnCheckEnableCtl()
  511. /*++
  512. Routine Description:
  513. 'Enable CTL' checkbox handler
  514. Arguments:
  515. None
  516. Return Value:
  517. None
  518. --*/
  519. {
  520. //
  521. // Since this is local only, if we are remote and the user checks the
  522. // box, then we should alert them to the situation and then do nothing.
  523. //
  524. if (!m_fIsLocal)
  525. {
  526. DoHelpMessageBox(m_hWnd,IDS_CTL_LOCAL_ONLY, MB_APPLMODAL | MB_OK | MB_ICONINFORMATION, 0);
  527. return;
  528. }
  529. m_fEnableCtl = !m_fEnableCtl;
  530. //
  531. // If we are now disabling, record the current cert and then blank it
  532. //
  533. if (!m_fEnableCtl)
  534. {
  535. m_iLastUsedCert = m_combo_ctl.GetCurSel();
  536. m_combo_ctl.SetCurSel(-1);
  537. }
  538. else
  539. {
  540. //
  541. // We are enabling, use the last recorded cert
  542. //
  543. m_combo_ctl.SetCurSel(m_iLastUsedCert);
  544. }
  545. m_bCTLDirty = TRUE;
  546. SetControlStates();
  547. }
  548. void
  549. CSecCommDlg::OnButtonEditCtl()
  550. /*++
  551. Routine Description:
  552. "Edit CTL" button handler
  553. Arguments:
  554. None
  555. Return Value:
  556. None
  557. --*/
  558. {
  559. //
  560. // Get the index of the selected item
  561. //
  562. INT iSel = m_combo_ctl.GetCurSel();
  563. ASSERT( iSel != CB_ERR );
  564. //
  565. // Get the selected CTL context
  566. //
  567. PCCTL_CONTEXT pCTL = (PCCTL_CONTEXT)m_combo_ctl.GetItemData(iSel);
  568. //
  569. // Pass in the selected CTL context to edit it
  570. //
  571. PCCTL_CONTEXT pCTLNew = CallCTLWizard( pCTL );
  572. //
  573. // If the CTL on the item has changed, then update the private data item
  574. //
  575. if (pCTLNew && pCTLNew != pCTL)
  576. {
  577. //
  578. // start be deleting the current item from the list
  579. //
  580. m_combo_ctl.DeleteString(iSel);
  581. //
  582. // free the old context
  583. //
  584. CertFreeCTLContext(pCTL);
  585. //
  586. // now add the new one and select it.
  587. //
  588. AddCTLToList(pCTLNew, TRUE);
  589. SetControlStates();
  590. //
  591. // set the dirty flag
  592. //
  593. m_bCTLDirty = TRUE;
  594. }
  595. }
  596. void
  597. CSecCommDlg::OnButtonNewCtl()
  598. /*++
  599. Routine Description:
  600. "New CTL" button handler
  601. Arguments:
  602. None
  603. Return Value:
  604. None
  605. --*/
  606. {
  607. //
  608. // Pass in NULL to create a new CTL
  609. //
  610. PCCTL_CONTEXT pCTL = CallCTLWizard(NULL);
  611. //
  612. // If a CTL was created, add it to the list and select it.
  613. //
  614. if (pCTL != NULL)
  615. {
  616. AddCTLToList(pCTL, TRUE);
  617. SetControlStates();
  618. m_bCTLDirty = TRUE;
  619. }
  620. }
  621. PCCTL_CONTEXT
  622. CSecCommDlg::CallCTLWizard(
  623. IN PCCTL_CONTEXT pCTLSrc
  624. )
  625. /*++
  626. Routine Description:
  627. Adds a CTL to the drop down CTL list. Note that the context pointers are
  628. set as the private data on the list items. This means that they will need
  629. to be de-referenced when this object is destroyed. See the
  630. routine CleanUpCTLList.
  631. Arguments:
  632. PCCTL_CONTEXT pctl ctl context pointer of the ctl being added
  633. BOOL fSelect flag specifying if this ctl should be selected after it
  634. is added
  635. Return Value:
  636. returns TRUE if successful
  637. --*/
  638. {
  639. PCCTL_CONTEXT pCTLOut = NULL;
  640. CRYPTUI_WIZ_BUILDCTL_NEW_CTL_INFO newInfo;
  641. CTL_USAGE useInfo;
  642. CString szFriendly;
  643. CString szDescription;
  644. CString szListIdentifier;
  645. LPOLESTR pszListIdentifier = NULL;
  646. LPCSTR rgbpszUsageArray[2];
  647. //
  648. // Prepare the main src structure
  649. //
  650. CRYPTUI_WIZ_BUILDCTL_SRC_INFO srcInfo;
  651. ZeroMemory( &srcInfo, sizeof(srcInfo) );
  652. srcInfo.dwSize = sizeof(srcInfo);
  653. //
  654. // If we are editing an existing CTL then we do one thing
  655. //
  656. if ( pCTLSrc )
  657. {
  658. srcInfo.dwSourceChoice = CRYPTUI_WIZ_BUILDCTL_SRC_EXISTING_CTL;
  659. srcInfo.pCTLContext = pCTLSrc;
  660. }
  661. else
  662. {
  663. //
  664. // Prepare the usage arrays
  665. //
  666. ZeroMemory( &rgbpszUsageArray, sizeof(rgbpszUsageArray) );
  667. rgbpszUsageArray[0] = szOID_IIS_VIRTUAL_SERVER;
  668. //
  669. // Must also have client auth - or else no certs show up in the list!
  670. //
  671. rgbpszUsageArray[1] = szOID_PKIX_KP_CLIENT_AUTH;
  672. ZeroMemory( &useInfo, sizeof(useInfo) );
  673. useInfo.cUsageIdentifier = 2;
  674. useInfo.rgpszUsageIdentifier = (PCHAR*)&rgbpszUsageArray;
  675. //
  676. // Prep the new ctl structure, which may or may not get used
  677. //
  678. ZeroMemory( &newInfo, sizeof(newInfo) );
  679. //
  680. // We making a new CTL, fill in the rest of the stuff
  681. //
  682. srcInfo.dwSourceChoice = CRYPTUI_WIZ_BUILDCTL_SRC_NEW_CTL;
  683. srcInfo.pNewCTLInfo = &newInfo;
  684. //
  685. // Load the friendly name and the description
  686. //
  687. szFriendly.LoadString(IDS_CTL_NEW);
  688. szDescription.LoadString(IDS_CTL_DESCRIPTION);
  689. //
  690. // Create a guid string for the identifier
  691. //
  692. GUID id;
  693. HRESULT hres = CoCreateGuid(&id);
  694. hres = StringFromGUID2(id, szListIdentifier.GetBuffer(1000), 1000);
  695. szListIdentifier.ReleaseBuffer();
  696. //
  697. // Fill in the newInfo structure
  698. //
  699. newInfo.dwSize = sizeof(newInfo);
  700. //
  701. // For now - don't set the usage
  702. //
  703. newInfo.pSubjectUsage = &useInfo;
  704. //
  705. // Put the generated list identifier into place
  706. //
  707. newInfo.pwszListIdentifier = (LPTSTR)(LPCTSTR)szListIdentifier;
  708. //
  709. // Fill in the friendly strings that were loaded from the resources
  710. //
  711. newInfo.pwszFriendlyName = (LPTSTR)(LPCTSTR)szFriendly;
  712. newInfo.pwszDescription = (LPTSTR)(LPCTSTR)szDescription;
  713. }
  714. //
  715. // Make the call to the CTL wizard
  716. //
  717. if (!CryptUIWizBuildCTL(
  718. CRYPTUI_WIZ_BUILDCTL_SKIP_SIGNING |
  719. CRYPTUI_WIZ_BUILDCTL_SKIP_PURPOSE |
  720. CRYPTUI_WIZ_BUILDCTL_SKIP_DESTINATION,
  721. m_hWnd,
  722. NULL,
  723. &srcInfo,
  724. NULL,
  725. &pCTLOut
  726. ))
  727. {
  728. //
  729. // The user canceled the CTL wizard or it failed in general.
  730. // the CTL wizard puts up its own error dialogs
  731. //
  732. return NULL;
  733. }
  734. //
  735. // Add the certificate context to the store
  736. //
  737. if (pCTLOut != NULL)
  738. {
  739. PCCTL_CONTEXT pCTLAdded = NULL;
  740. if (CertAddCTLContextToStore(
  741. m_hCTLStore,
  742. pCTLOut,
  743. CERT_STORE_ADD_REPLACE_EXISTING,
  744. &pCTLAdded
  745. ))
  746. {
  747. CertFreeCTLContext( pCTLOut );
  748. pCTLOut = pCTLAdded;
  749. }
  750. else
  751. {
  752. CertFreeCTLContext( pCTLOut );
  753. pCTLOut = NULL;
  754. }
  755. }
  756. return pCTLOut;
  757. }
  758. BOOL
  759. CSecCommDlg::AddCTLToList(
  760. IN PCCTL_CONTEXT pCTL,
  761. IN BOOL fSelect
  762. )
  763. /*++
  764. Routine Description:
  765. Adds a CTL to the drop down CTL list. Note that the context pointers are
  766. set as the private data on the list items. This means that they will need
  767. to be de-referenced when this object is destroyed. See the
  768. routine CleanUpCTLList.
  769. This routine by boydm
  770. Arguments:
  771. PCCTL_CONTEXT pctl ctl context pointer of the ctl being added
  772. BOOL fSelect - flag specifying if this ctl should be selected after it
  773. is added
  774. Return Value:
  775. returns TRUE if successful
  776. --*/
  777. {
  778. BOOL fSuccess;
  779. ASSERT(pCTL != NULL);
  780. if (!pCTL)
  781. {
  782. return FALSE;
  783. }
  784. //
  785. // First, we extract the friendly name from the CTL.
  786. //
  787. CString szFriendlyName; // the friendly name
  788. DWORD cbName = 0; // count of BYTES for the name, not chars
  789. //
  790. // Find out how much space we need
  791. //
  792. fSuccess = CertGetCTLContextProperty(
  793. pCTL,
  794. CERT_FRIENDLY_NAME_PROP_ID,
  795. NULL,
  796. &cbName
  797. );
  798. //
  799. // Increase buffer just to cover any nulls just to be safe
  800. //
  801. cbName += 2;
  802. //
  803. // Get the friendly name
  804. //
  805. fSuccess = CertGetCTLContextProperty(
  806. pCTL,
  807. CERT_FRIENDLY_NAME_PROP_ID,
  808. szFriendlyName.GetBuffer(cbName),
  809. &cbName
  810. );
  811. szFriendlyName.ReleaseBuffer();
  812. //
  813. // If we did not get the name, then load the default name.
  814. // The friendly name is an optional parameter in the CTL so it
  815. // is OK if it is not there.
  816. //
  817. if (!fSuccess)
  818. {
  819. szFriendlyName.LoadString(IDS_CTL_UNNAMED);
  820. }
  821. //
  822. // Add the friendly name string to the drop down CTL list and record
  823. // the index of the newly created item
  824. //
  825. INT iCTLPosition = m_combo_ctl.AddString(szFriendlyName);
  826. //
  827. // If it worked, then add the context pointer to the item as private data
  828. //
  829. if (iCTLPosition >=0)
  830. {
  831. m_combo_ctl.SetItemData(iCTLPosition, (ULONG_PTR)pCTL);
  832. //
  833. // if we have been told to select the CTL, do so at this point
  834. //
  835. if (fSelect)
  836. {
  837. m_combo_ctl.SetCurSel(iCTLPosition);
  838. }
  839. }
  840. //
  841. // Return TRUE if we successfully added the CTL
  842. //
  843. return (iCTLPosition >=0);
  844. }
  845. void
  846. CSecCommDlg::InitializeCTLList()
  847. /*++
  848. Routine Description:
  849. Initializes the CTL drop down box by opening the CTL store pointer
  850. to the target store and filling in the CTL list box with the enumerated
  851. values.
  852. This routine by boydm
  853. Arguments:
  854. None
  855. Return Value:
  856. None
  857. --*/
  858. {
  859. //
  860. // For now this is Local ONLY
  861. //
  862. if (!m_fIsLocal)
  863. {
  864. return;
  865. }
  866. //
  867. // Build the remote name for the store.
  868. // It takes the form of "\\MACHINE_NAME\STORENAME"
  869. // The store name is always "MY" and is define above. The machine
  870. // name is the name of the machine being edited. The leading \\ in the
  871. // machine name is optional so we will skip it in this case
  872. //
  873. CString szStore;
  874. //
  875. // Start by adding the machine name that we are targeting
  876. //
  877. szStore = m_strServerName;
  878. //
  879. // Add the specific store name
  880. //
  881. szStore += _T('\\');
  882. szStore += m_strCTLStoreName;
  883. //
  884. // BUGBUG just use MY for now
  885. //
  886. szStore = m_strCTLStoreName;
  887. //
  888. // Open the store
  889. //
  890. m_hCTLStore = CertOpenStore( CERT_STORE_PROV_SYSTEM,
  891. 0,
  892. NULL,
  893. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  894. szStore
  895. );
  896. //
  897. // If we failed to open the store, then we will be unable to do anything
  898. // with CTLs on this machine at all. Disable everything having to do
  899. // with the CTL controls.
  900. //
  901. if (!m_hCTLStore)
  902. {
  903. m_fEnableCtl = FALSE;
  904. //
  905. // Return early as we have no need to enumerate the CTLs
  906. //
  907. return;
  908. }
  909. //
  910. // Enumerate all the CTLs in the store and add them to the drop-down list
  911. //
  912. PCCTL_CONTEXT pCTLEnum = NULL;
  913. //
  914. // Enumerate undil NULL is returned. Note that CertEnumCTLsInStore
  915. // free the context passed into pCTLEnum if it is non NULL. Thus we
  916. // need to create a duplicate of it to add to the drop-list
  917. //
  918. while (pCTLEnum = CertEnumCTLsInStore(m_hCTLStore, pCTLEnum))
  919. {
  920. //
  921. // Make a duplicate of the CTL context for storing in thte list
  922. //
  923. PCCTL_CONTEXT pCTL = CertDuplicateCTLContext(pCTLEnum);
  924. if (!pCTL)
  925. {
  926. //
  927. // Duplication Failed
  928. //
  929. continue;
  930. }
  931. //
  932. // The list identifier is a inherint value of the context and doesn't
  933. // need to be read in separately. We can just referenece it
  934. //
  935. BOOL fIsCurrentCTL = FALSE;
  936. if (pCTL->pCtlInfo
  937. && pCTL->pCtlInfo->ListIdentifier.cbData >= 2
  938. && pCTL->pCtlInfo->ListIdentifier.cbData)
  939. {
  940. //
  941. // If the identifiers are the same, then this is our default CTL
  942. //
  943. fIsCurrentCTL = (wcsncmp(
  944. (LPCTSTR)m_strCTLIdentifier,
  945. (PWCHAR)pCTL->pCtlInfo->ListIdentifier.pbData,
  946. pCTL->pCtlInfo->ListIdentifier.cbData
  947. ) == 0);
  948. // fIsCurrentCTL = ( m_strCTLIdentifier == (PWCHAR)pCTL->pCtlInfo->ListIdentifier.pbData );
  949. }
  950. //
  951. // Add the CTL to the list
  952. //
  953. AddCTLToList(pCTL, fIsCurrentCTL);
  954. }
  955. }
  956. void
  957. CSecCommDlg::CleanUpCTLList()
  958. /*++
  959. Routine Description:
  960. Dereferences all the CTL context pointers in the private data of
  961. the items in the CTL combo box.
  962. Then it closes the CTL store handle
  963. This routine by boydm
  964. Arguments:
  965. None
  966. Return Value:
  967. None
  968. --*/
  969. {
  970. DWORD cItems = m_combo_ctl.GetCount();
  971. //
  972. // Loop through each item and free its reference to the CTL pointer
  973. //
  974. for (DWORD i = 0; i < cItems; ++i)
  975. {
  976. //
  977. // Get the CTL context pointer from the item's private data
  978. //
  979. PCCTL_CONTEXT pCTL = (PCCTL_CONTEXT)m_combo_ctl.GetItemData(i);
  980. if (pCTL)
  981. {
  982. CertFreeCTLContext(pCTL);
  983. }
  984. }
  985. //
  986. // Close the handle to the store that contains the CTLs
  987. //
  988. if (m_hCTLStore)
  989. {
  990. CertCloseStore( m_hCTLStore, CERT_CLOSE_STORE_FORCE_FLAG );
  991. m_hCTLStore = NULL;
  992. }
  993. }
  994. void
  995. CSecCommDlg::OnSelchangeComboCtl()
  996. /*++
  997. Routine Description:
  998. The selection in the drop-down list changed
  999. This routine by boydm
  1000. Arguments:
  1001. None
  1002. Return Value:
  1003. None
  1004. --*/
  1005. {
  1006. SetControlStates();
  1007. m_bCTLDirty = TRUE;
  1008. }
  1009. void
  1010. CSecCommDlg::OnDestroy()
  1011. /*++
  1012. Routine Description:
  1013. WM_DESTROY handler. Clean up internal data
  1014. Arguments:
  1015. None
  1016. Return Value:
  1017. None
  1018. --*/
  1019. {
  1020. CDialog::OnDestroy();
  1021. CleanUpCTLList();
  1022. }