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.

834 lines
13 KiB

  1. /*++
  2. Copyright (c) 1994-1998 Microsoft Corporation
  3. Module Name :
  4. security.cpp
  5. Abstract:
  6. FTP Security Property Page
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Project:
  10. Internet Services Manager
  11. Revision History:
  12. --*/
  13. //
  14. // Include Files
  15. //
  16. #include "stdafx.h"
  17. #include "fscfg.h"
  18. #include "accessdl.h"
  19. #include "security.h"
  20. #ifdef _DEBUG
  21. #define new DEBUG_NEW
  22. #undef THIS_FILE
  23. static char THIS_FILE[] = __FILE__;
  24. #endif
  25. //
  26. // Needed for granted/denied icons
  27. //
  28. #include "..\comprop\resource.h"
  29. IMPLEMENT_DYNCREATE(CFtpSecurityPage, CInetPropertyPage)
  30. CFtpSecurityPage::CFtpSecurityPage(
  31. IN CInetPropertySheet * pSheet
  32. )
  33. /*++
  34. Routine Description:
  35. Constructor
  36. Arguments:
  37. CInetPropertySheet * pSheet : Sheet object
  38. Return Value:
  39. N/A
  40. --*/
  41. : CInetPropertyPage(
  42. CFtpSecurityPage::IDD,
  43. pSheet,
  44. USE_DEFAULT_CAPTION,
  45. TRUE // Enable enhanced fonts
  46. ),
  47. m_ListBoxRes(
  48. IDB_ACCESS,
  49. m_list_IpAddresses.nBitmaps
  50. ),
  51. m_oblAccessList(),
  52. m_list_IpAddresses(TRUE),
  53. m_fIpDirty(FALSE),
  54. m_fOldDefaultGranted(TRUE),
  55. m_fDefaultGranted(TRUE) // By default, we grant access
  56. {
  57. #if 0 // Keep class wizard happy
  58. //{{AFX_DATA_INIT(CFtpSecurityPage)
  59. m_nGrantedDenied = 0;
  60. //}}AFX_DATA_INIT
  61. #endif // 0
  62. m_list_IpAddresses.AttachResources(&m_ListBoxRes);
  63. }
  64. CFtpSecurityPage::~CFtpSecurityPage()
  65. /*++
  66. Routine Description:
  67. Destructor
  68. Arguments:
  69. N/A
  70. Return Value:
  71. N/A
  72. --*/
  73. {
  74. //
  75. // The access list will clean itself up
  76. //
  77. }
  78. void
  79. CFtpSecurityPage::DoDataExchange(
  80. IN CDataExchange * pDX
  81. )
  82. /*++
  83. Routine Description:
  84. Initialise/Store control data
  85. Arguments:
  86. CDataExchange * pDX - DDX/DDV control structure
  87. Return Value:
  88. None
  89. --*/
  90. {
  91. CInetPropertyPage::DoDataExchange(pDX);
  92. //{{AFX_DATA_MAP(CFtpSecurityPage)
  93. DDX_Control(pDX, IDC_BUTTON_REMOVE, m_button_Remove);
  94. DDX_Control(pDX, IDC_BUTTON_EDIT, m_button_Edit);
  95. DDX_Control(pDX, IDC_BUTTON_ADD, m_button_Add);
  96. DDX_Control(pDX, IDC_ICON_GRANTED, m_icon_Granted);
  97. DDX_Control(pDX, IDC_ICON_DENIED, m_icon_Denied);
  98. DDX_Control(pDX, IDC_RADIO_GRANTED, m_radio_Granted);
  99. DDX_Radio(pDX, IDC_RADIO_GRANTED, m_nGrantedDenied);
  100. //}}AFX_DATA_MAP
  101. //
  102. // Private DDX/DDV Routines
  103. //
  104. DDX_Control(pDX, IDC_RADIO_DENIED, m_radio_Denied);
  105. DDX_Control(pDX, IDC_LIST_IP_ADDRESSES, m_list_IpAddresses);
  106. }
  107. //
  108. // Message Map
  109. //
  110. BEGIN_MESSAGE_MAP(CFtpSecurityPage, CInetPropertyPage)
  111. //{{AFX_MSG_MAP(CFtpSecurityPage)
  112. ON_BN_CLICKED(IDC_BUTTON_ADD, OnButtonAdd)
  113. ON_BN_CLICKED(IDC_BUTTON_EDIT, OnButtonEdit)
  114. ON_BN_CLICKED(IDC_BUTTON_REMOVE, OnButtonRemove)
  115. ON_BN_CLICKED(IDC_RADIO_GRANTED, OnRadioGranted)
  116. ON_BN_CLICKED(IDC_RADIO_DENIED, OnRadioDenied)
  117. ON_LBN_DBLCLK(IDC_LIST_IP_ADDRESSES, OnDblclkListIpAddresses)
  118. ON_LBN_ERRSPACE(IDC_LIST_IP_ADDRESSES, OnErrspaceListIpAddresses)
  119. ON_LBN_SELCHANGE(IDC_LIST_IP_ADDRESSES, OnSelchangeListIpAddresses)
  120. ON_WM_VKEYTOITEM()
  121. //}}AFX_MSG_MAP
  122. END_MESSAGE_MAP()
  123. /* virtual */
  124. HRESULT
  125. CFtpSecurityPage::FetchLoadedValues()
  126. /*++
  127. Routine Description:
  128. Move configuration data from sheet to dialog controls
  129. Arguments:
  130. None
  131. Return Value:
  132. HRESULT
  133. --*/
  134. {
  135. m_nGrantedDenied = 0;
  136. //
  137. // Build the IPL list
  138. //
  139. CError err(BuildIplOblistFromBlob(
  140. ((CFtpSheet *)GetSheet())->GetDirectoryProperties().m_ipl,
  141. m_oblAccessList,
  142. m_fDefaultGranted
  143. ));
  144. err.MessageBoxOnFailure();
  145. m_nGrantedDenied = m_fDefaultGranted ? DEFAULT_GRANTED : DEFAULT_DENIED;
  146. m_fOldDefaultGranted = m_fDefaultGranted;
  147. return S_OK;
  148. }
  149. /* virtual */
  150. HRESULT
  151. CFtpSecurityPage::SaveInfo()
  152. /*++
  153. Routine Description:
  154. Save the information on this property page
  155. Arguments:
  156. None
  157. Return Value:
  158. Error return code
  159. --*/
  160. {
  161. ASSERT(IsDirty());
  162. TRACEEOLID("Saving FTP security page now...");
  163. BOOL fIplDirty = m_fIpDirty || (m_fOldDefaultGranted != m_fDefaultGranted);
  164. //
  165. // Use m_ notation because the message crackers require it.
  166. //
  167. CBlob m_ipl;
  168. if (fIplDirty)
  169. {
  170. BuildIplBlob(m_oblAccessList, m_fDefaultGranted, m_ipl);
  171. }
  172. CError err;
  173. BeginWaitCursor();
  174. BEGIN_META_DIR_WRITE(CFtpSheet)
  175. if (fIplDirty)
  176. {
  177. STORE_DIR_DATA_ON_SHEET(m_ipl);
  178. }
  179. END_META_DIR_WRITE(err)
  180. EndWaitCursor();
  181. if (err.Succeeded())
  182. {
  183. m_fIpDirty = FALSE;
  184. m_fOldDefaultGranted = m_fDefaultGranted;
  185. }
  186. return err;
  187. }
  188. //
  189. // Message Handlers
  190. //
  191. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  192. void
  193. CFtpSecurityPage::OnButtonAdd()
  194. /*++
  195. Routine Description:
  196. 'Add' button handler
  197. Arguments:
  198. None
  199. Return Value:
  200. None
  201. --*/
  202. {
  203. if (ShowPropertiesDialog(TRUE) == IDOK)
  204. {
  205. SetControlStates();
  206. m_fIpDirty = TRUE;
  207. OnItemChanged();
  208. }
  209. }
  210. void
  211. CFtpSecurityPage::OnButtonEdit()
  212. /*++
  213. Routine Description:
  214. 'Edit' button handler
  215. Arguments:
  216. None
  217. Return Value:
  218. None
  219. --*/
  220. {
  221. if (ShowPropertiesDialog(FALSE) == IDOK)
  222. {
  223. SetControlStates();
  224. m_fIpDirty = TRUE;
  225. OnItemChanged();
  226. }
  227. }
  228. void
  229. CFtpSecurityPage::OnButtonRemove()
  230. /*++
  231. Routine Description:
  232. 'Remove' button handler
  233. Arguments:
  234. None
  235. Return Value:
  236. None
  237. --*/
  238. {
  239. int nSel = 0;
  240. int nCurSel = m_list_IpAddresses.GetCurSel();
  241. while (m_list_IpAddresses.GetNextSelectedItem(&nSel))
  242. {
  243. m_oblAccessList.RemoveIndex(nSel);
  244. m_list_IpAddresses.DeleteString(nSel);
  245. }
  246. m_fIpDirty = TRUE;
  247. OnItemChanged();
  248. if (nCurSel > 0)
  249. {
  250. --nCurSel;
  251. }
  252. m_list_IpAddresses.SetCurSel(nCurSel);
  253. if (!SetControlStates())
  254. {
  255. m_button_Add.SetFocus();
  256. }
  257. }
  258. BOOL
  259. CFtpSecurityPage::SetControlStates()
  260. /*++
  261. Routine Description:
  262. Set the enabled status of the controls depending on the current
  263. state of the dialog
  264. Arguments:
  265. None
  266. Return Value:
  267. TRUE if at least one item is currently selected in the listbox
  268. --*/
  269. {
  270. BOOL fSomeSelection = m_list_IpAddresses.GetSelCount() > 0;
  271. m_button_Edit.EnableWindow(m_list_IpAddresses.GetSelCount() == 1);
  272. m_button_Remove.EnableWindow(m_list_IpAddresses.GetSelCount() > 0);
  273. return fSomeSelection;
  274. }
  275. void
  276. CFtpSecurityPage::FillListBox(
  277. IN CIPAccessDescriptor * pSelection OPTIONAL
  278. )
  279. /*++
  280. Routine Description:
  281. Populate the listbox with the access list
  282. entries
  283. Arguments:
  284. CIPAccessDescriptor * pSelection : Item to be selected or NULL.
  285. Return Value:
  286. None
  287. --*/
  288. {
  289. CObListIter obli(m_oblAccessList);
  290. const CIPAccessDescriptor * pAccess;
  291. m_list_IpAddresses.SetRedraw(FALSE);
  292. m_list_IpAddresses.ResetContent();
  293. int cItems = 0 ;
  294. int nSel = LB_ERR, nItem;
  295. for ( /**/ ; pAccess = (CIPAccessDescriptor *)obli.Next(); ++cItems)
  296. {
  297. //
  298. // We only list those not adhering to the default
  299. //
  300. if (pAccess->HasAccess() != m_fDefaultGranted)
  301. {
  302. nItem = m_list_IpAddresses.AddItem(pAccess);
  303. if (pAccess == pSelection)
  304. {
  305. //
  306. // Found item to be selected
  307. //
  308. nSel = nItem;
  309. }
  310. }
  311. }
  312. m_list_IpAddresses.SetCurSel(nSel);
  313. m_list_IpAddresses.SetRedraw(TRUE);
  314. }
  315. DWORD
  316. CFtpSecurityPage::SortAccessList()
  317. /*++
  318. Routine Description:
  319. Sorting the access list by grant denied and ip address
  320. FillListBox() should be called after this because
  321. the listbox will no longer reflect the true status
  322. of the list of directories.
  323. Arguments:
  324. None
  325. Return Value:
  326. Error return code
  327. --*/
  328. {
  329. BeginWaitCursor();
  330. DWORD dw = m_oblAccessList.Sort(
  331. (CObjectPlus::PCOBJPLUS_ORDER_FUNC)&CIPAccessDescriptor::OrderByAddress);
  332. EndWaitCursor();
  333. return dw;
  334. }
  335. INT_PTR
  336. CFtpSecurityPage::ShowPropertiesDialog(
  337. IN BOOL fAdd
  338. )
  339. /*++
  340. Routine Description:
  341. Bring up the dialog used for add or edit. Return the value returned
  342. by the dialog
  343. Arguments:
  344. BOOL fAdd : If TRUE, create new item. Otherwise, edit existing item
  345. Return Value:
  346. Dialog return code (IDOK/IDCANCEL)
  347. --*/
  348. {
  349. //
  350. // Bring up the dialog
  351. //
  352. CIPAccessDescriptor * pAccess = NULL;
  353. int nCurSel = LB_ERR;
  354. if (!fAdd)
  355. {
  356. //
  357. // Edit existing entry -- there better be only one...
  358. //
  359. pAccess = m_list_IpAddresses.GetSelectedItem();
  360. ASSERT(pAccess != NULL);
  361. if (pAccess == NULL)
  362. {
  363. //
  364. // Double click?
  365. //
  366. return IDCANCEL;
  367. }
  368. }
  369. CIPAccessDlg dlgAccess(
  370. m_fDefaultGranted,
  371. pAccess,
  372. &m_oblAccessList,
  373. this
  374. );
  375. INT_PTR nReturn = dlgAccess.DoModal();
  376. if (nReturn == IDOK)
  377. {
  378. CError err;
  379. ASSERT(pAccess != NULL);
  380. if (pAccess == NULL)
  381. {
  382. err = ERROR_NOT_ENOUGH_MEMORY;
  383. }
  384. else
  385. {
  386. try
  387. {
  388. if (fAdd)
  389. {
  390. m_oblAccessList.AddTail(pAccess);
  391. }
  392. SortAccessList();
  393. FillListBox(pAccess);
  394. }
  395. catch(CMemoryException * e)
  396. {
  397. err = ERROR_NOT_ENOUGH_MEMORY;
  398. e->Delete();
  399. }
  400. }
  401. err.MessageBoxOnFailure();
  402. }
  403. return nReturn;
  404. }
  405. void
  406. CFtpSecurityPage::OnDblclkListIpAddresses()
  407. /*++
  408. Routine Description:
  409. Map listbox double click to the edit button
  410. Arguments:
  411. None
  412. Return Value:
  413. None
  414. --*/
  415. {
  416. OnButtonEdit();
  417. }
  418. void
  419. CFtpSecurityPage::OnErrspaceListIpAddresses()
  420. /*++
  421. Routine Description:
  422. Handle error condition in the ip address listbox
  423. Arguments:
  424. None
  425. Return Value:
  426. None
  427. --*/
  428. {
  429. SetControlStates();
  430. }
  431. void
  432. CFtpSecurityPage::OnSelchangeListIpAddresses()
  433. /*++
  434. Routine Description:
  435. Handle change in the selection of the listbox
  436. Arguments:
  437. None
  438. Return Value:
  439. None
  440. --*/
  441. {
  442. SetControlStates();
  443. }
  444. void
  445. CFtpSecurityPage::OnItemChanged()
  446. /*++
  447. Routine Description:
  448. All EN_CHANGE messages map to this function
  449. Arguments:
  450. None
  451. Return Value:
  452. None
  453. --*/
  454. {
  455. SetModified(TRUE);
  456. }
  457. BOOL
  458. CFtpSecurityPage::OnInitDialog()
  459. /*++
  460. Routine Description:
  461. WM_INITDIALOG handler. Initialize the dialog.
  462. Arguments:
  463. None.
  464. Return Value:
  465. TRUE if focus is to be set automatically, FALSE if the focus
  466. is already set.
  467. --*/
  468. {
  469. CInetPropertyPage::OnInitDialog();
  470. m_icon_Granted.SetIcon(::AfxGetApp()->LoadIcon(IDI_GRANTED));
  471. m_icon_Denied.SetIcon(::AfxGetApp()->LoadIcon(IDI_DENIED));
  472. m_list_IpAddresses.Initialize();
  473. m_list_IpAddresses.EnableWindow(HasIPAccessCheck());
  474. m_button_Add.EnableWindow(HasIPAccessCheck());
  475. GetDlgItem(IDC_RADIO_GRANTED)->EnableWindow(HasIPAccessCheck());
  476. GetDlgItem(IDC_RADIO_DENIED)->EnableWindow(HasIPAccessCheck());
  477. GetDlgItem(IDC_ICON_GRANTED)->EnableWindow(HasIPAccessCheck());
  478. GetDlgItem(IDC_ICON_DENIED)->EnableWindow(HasIPAccessCheck());
  479. FillListBox();
  480. SetControlStates();
  481. return TRUE;
  482. }
  483. void
  484. CFtpSecurityPage::OnRadioGranted()
  485. /*++
  486. Routine Description:
  487. Granted by default has been selected.
  488. Refill the listbox with items that have
  489. been explicitly denied. Although we can
  490. only have a deny list or a grant list,
  491. we keep both of them around until it comes
  492. time to saving the information.
  493. Arguments:
  494. None
  495. Return Value:
  496. None
  497. --*/
  498. {
  499. if (!m_fDefaultGranted)
  500. {
  501. m_fDefaultGranted = TRUE;
  502. FillListBox();
  503. OnItemChanged();
  504. SetControlStates();
  505. }
  506. }
  507. void
  508. CFtpSecurityPage::OnRadioDenied()
  509. /*++
  510. Routine Description:
  511. As above, but reverse granted and denied
  512. Arguments:
  513. None
  514. Return Value:
  515. None
  516. --*/
  517. {
  518. if (m_fDefaultGranted)
  519. {
  520. m_fDefaultGranted = FALSE;
  521. FillListBox();
  522. OnItemChanged();
  523. SetControlStates();
  524. }
  525. }
  526. int
  527. CFtpSecurityPage::OnVKeyToItem(
  528. IN UINT nKey,
  529. IN CListBox * pListBox,
  530. IN UINT nIndex
  531. )
  532. /*++
  533. Routine Description:
  534. Map insert and delete keys for the listbox
  535. Arguments:
  536. UINT nKey : Key pressed
  537. CListBox * pListBox : Listbox
  538. UINT nIndex : Index selected
  539. Return Value:
  540. -2 if fully handled, -1 if partially handled, 0+ if not
  541. handled at all
  542. --*/
  543. {
  544. switch(nKey)
  545. {
  546. case VK_DELETE:
  547. OnButtonRemove();
  548. break;
  549. case VK_INSERT:
  550. OnButtonAdd();
  551. break;
  552. default:
  553. //
  554. // Not completely handled by this function, let
  555. // windows handle the remaining default action.
  556. //
  557. return -1;
  558. }
  559. //
  560. // No further action is neccesary.
  561. //
  562. return -2;
  563. }