| /******************************************************************************* |
| * Copyright (c) 2008, 2017 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.equinox.internal.security.ui.storage; |
| |
| import java.util.HashSet; |
| import java.util.Set; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.preferences.*; |
| import org.eclipse.equinox.internal.security.storage.friends.*; |
| import org.eclipse.equinox.internal.security.ui.nls.SecUIMessages; |
| import org.eclipse.equinox.security.storage.ISecurePreferences; |
| import org.eclipse.equinox.security.storage.SecurePreferencesFactory; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.layout.*; |
| import org.eclipse.jface.viewers.ColumnWeightData; |
| import org.eclipse.jface.viewers.TableLayout; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.*; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.*; |
| import org.osgi.service.prefs.BackingStoreException; |
| import org.osgi.service.prefs.Preferences; |
| |
| public class TabPassword { |
| |
| private static final String PREFERENCES_PLUGIN = "org.eclipse.equinox.security"; //$NON-NLS-1$ |
| |
| private final static String PASSWORD_RECOVERY_NODE = "/org.eclipse.equinox.secure.storage/recovery/"; //$NON-NLS-1$ |
| |
| protected Table providerTable; |
| |
| protected Button buttonClearPassword; |
| protected Button buttonChangePassword; |
| protected Button buttonRecoverPassword; |
| |
| protected Text detailsText; |
| |
| protected boolean providerModified = false; |
| |
| public TabPassword(TabFolder folder, int index, final Shell shell) { |
| TabItem tab = new TabItem(folder, SWT.NONE, index); |
| tab.setText(SecUIMessages.tabPassword); |
| Composite page = new Composite(folder, SWT.NONE); |
| page.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false)); |
| tab.setControl(page); |
| |
| Group passwordGroup = new Group(page, SWT.NONE); |
| passwordGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); |
| passwordGroup.setLayout(new GridLayout(2, false)); |
| passwordGroup.setText(SecUIMessages.passwordCacheGroup); |
| |
| buttonClearPassword = new Button(passwordGroup, SWT.PUSH); |
| buttonClearPassword.setText(SecUIMessages.logoutButton); |
| buttonClearPassword.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false, false)); |
| buttonClearPassword.addSelectionListener(new SelectionAdapter() { |
| |
| public void widgetSelected(SelectionEvent e) { |
| InternalExchangeUtils.passwordProvidersReset(); |
| enableLogout(); |
| } |
| }); |
| setButtonSize(buttonClearPassword); |
| |
| Label passwordNote = new Label(passwordGroup, SWT.WRAP); |
| GridData labelData = new GridData(SWT.FILL, SWT.CENTER, true, false); |
| labelData.widthHint = 340; |
| passwordNote.setLayoutData(labelData); |
| passwordNote.setText(SecUIMessages.passwordCacheNote); |
| |
| Group providersGroup = new Group(page, SWT.NONE); |
| providersGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); |
| providersGroup.setLayout(new GridLayout()); |
| providersGroup.setText(SecUIMessages.providerGroup); |
| |
| Label providersNote = new Label(providersGroup, SWT.WRAP); |
| GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, false); |
| gridData.widthHint = 500; |
| providersNote.setLayoutData(gridData); |
| providersNote.setText(SecUIMessages.providerDescription); |
| |
| Composite providersComp = new Composite(providersGroup, SWT.NONE); |
| providersComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); |
| GridLayout gridLayout = new GridLayout(2, false); |
| gridLayout.marginHeight = 0; |
| gridLayout.marginWidth = 0; |
| providersComp.setLayout(gridLayout); |
| |
| providerTable = new Table(providersComp, SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION | SWT.CHECK); |
| GridData tableData = new GridData(GridData.FILL, GridData.FILL, true, true); |
| providerTable.setLayoutData(tableData); |
| providerTable.setLinesVisible(true); |
| providerTable.setHeaderVisible(true); |
| fillProviderTable(); |
| |
| providerTable.addSelectionListener(new SelectionListener() { |
| |
| public void widgetDefaultSelected(SelectionEvent e) { |
| // do nothing |
| } |
| |
| public void widgetSelected(SelectionEvent e) { |
| if ((e.detail & SWT.CHECK) != 0) |
| providerModified = true; |
| enableButtons(); |
| updateDescription(); |
| } |
| }); |
| GridDataFactory.defaultsFor(providerTable).span(1, 2).applyTo(providerTable); |
| |
| buttonChangePassword = new Button(providersComp, SWT.PUSH); |
| buttonChangePassword.setText(SecUIMessages.changePasswordButton); |
| buttonChangePassword.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, false, false)); |
| buttonChangePassword.addSelectionListener(new SelectionListener() { |
| |
| public void widgetDefaultSelected(SelectionEvent e) { |
| widgetSelected(e); |
| } |
| |
| public void widgetSelected(SelectionEvent e) { |
| PasswordProviderDescription selectedModule = getSelectedModule(); |
| if (selectedModule == null) |
| return; |
| String moduleID = getSelectedModuleID(); |
| ISecurePreferences rootNode = SecurePreferencesFactory.getDefault(); |
| if (selectedModule.hasHint(InternalExchangeUtils.HINT_PASSWORD_AUTOGEN)) { |
| // do replacement behind the scene without showing the wizard |
| changePassword(rootNode, moduleID, selectedModule.getName(), shell); |
| } else { |
| // show the wizard to provide separate "old" and "new" password entries |
| ChangePasswordWizardDialog dialog = new ChangePasswordWizardDialog(shell, rootNode, moduleID); |
| dialog.open(); |
| } |
| enableLogout(); |
| } |
| }); |
| setButtonSize(buttonChangePassword); |
| |
| buttonRecoverPassword = new Button(providersComp, SWT.PUSH); |
| buttonRecoverPassword.setText(SecUIMessages.recoverPasswordButton); |
| buttonRecoverPassword.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, false, false)); |
| buttonRecoverPassword.addSelectionListener(new SelectionListener() { |
| |
| public void widgetDefaultSelected(SelectionEvent e) { |
| widgetSelected(e); |
| } |
| |
| public void widgetSelected(SelectionEvent e) { |
| String moduleID = getSelectedModuleID(); |
| ISecurePreferences rootNode = SecurePreferencesFactory.getDefault(); |
| String[] questions = InternalExchangeUtils.getPasswordRecoveryQuestions(rootNode, moduleID); |
| if (questions.length == 0) |
| return; // no password recovery questions were setup |
| PasswordRecoveryDialog dialog = new PasswordRecoveryDialog(questions, shell, moduleID); |
| dialog.open(); |
| enableLogout(); |
| } |
| }); |
| setButtonSize(buttonRecoverPassword); |
| |
| enableButtons(); |
| |
| Label descriptionLabel = new Label(providersComp, SWT.NONE); |
| descriptionLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1)); |
| descriptionLabel.setText(SecUIMessages.providerDetails); |
| |
| detailsText = new Text(providersComp, SWT.MULTI | SWT.LEAD | SWT.BORDER | SWT.READ_ONLY | SWT.WRAP); |
| detailsText.setBackground(detailsText.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND)); |
| gridData = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1); |
| gridData.widthHint = 300; |
| gridData.heightHint = 65; |
| detailsText.setLayoutData(gridData); |
| updateDescription(); |
| |
| GridLayoutFactory.fillDefaults().margins(LayoutConstants.getSpacing()).generateLayout(page); |
| } |
| |
| private void fillProviderTable() { |
| TableColumn idColumn = new TableColumn(providerTable, SWT.LEAD); |
| idColumn.setText(SecUIMessages.idColumn); |
| |
| TableColumn priorityColumn = new TableColumn(providerTable, SWT.CENTER); |
| priorityColumn.setText(SecUIMessages.priorityColumn); |
| |
| HashSet<String> disabledModules = getDisabledModules(); |
| for (PasswordProviderDescription module : InternalExchangeUtils.passwordProvidersFind()) { |
| TableItem item = new TableItem(providerTable, SWT.NONE); |
| item.setText(new String[] {module.getName(), Integer.toString(module.getPriority())}); |
| item.setData(module); |
| if (disabledModules == null) |
| item.setChecked(true); |
| else |
| item.setChecked(!disabledModules.contains(module.getId())); |
| } |
| |
| TableLayout layout = new TableLayout(); |
| layout.addColumnData(new ColumnWeightData(5)); |
| layout.addColumnData(new ColumnWeightData(1)); |
| providerTable.setLayout(layout); |
| |
| if (providerTable.getItemCount() > 0) |
| providerTable.select(0); |
| } |
| |
| protected PasswordProviderDescription getSelectedModule() { |
| if (providerTable == null) |
| return null; |
| TableItem[] items = providerTable.getSelection(); |
| if (items.length == 0) |
| return null; |
| return ((PasswordProviderDescription) items[0].getData()); |
| } |
| |
| protected String getSelectedModuleID() { |
| PasswordProviderDescription selectedModule = getSelectedModule(); |
| if (selectedModule == null) |
| return null; |
| return selectedModule.getId(); |
| } |
| |
| protected void enableButtons() { |
| String moduleID = getSelectedModuleID(); |
| if (moduleID == null) { // nothing selected |
| buttonChangePassword.setEnabled(false); |
| buttonRecoverPassword.setEnabled(false); |
| } else { |
| buttonChangePassword.setEnabled(true); |
| |
| ISecurePreferences rootNode = SecurePreferencesFactory.getDefault(); |
| String path = PASSWORD_RECOVERY_NODE + moduleID; |
| boolean recoveryAvailable = rootNode.nodeExists(path); |
| buttonRecoverPassword.setEnabled(recoveryAvailable); |
| } |
| enableLogout(); |
| } |
| |
| protected HashSet<String> getDisabledModules() { |
| IScopeContext[] scopes = {ConfigurationScope.INSTANCE, DefaultScope.INSTANCE}; |
| IPreferencesService preferencesService = Platform.getPreferencesService(); |
| String defaultPreferenceValue = ""; //$NON-NLS-1$ |
| String tmp = preferencesService.getString(PREFERENCES_PLUGIN, IStorageConstants.DISABLED_PROVIDERS_KEY, defaultPreferenceValue, scopes); |
| HashSet<String> disabledModules = splitModuleIds(tmp); |
| return disabledModules; |
| } |
| |
| public void performDefaults() { |
| if (providerTable == null) |
| return; |
| Set<String> defaultDisabledModules = getDefaultDisabledModules(); |
| |
| TableItem[] items = providerTable.getItems(); |
| for (TableItem item : items) { |
| String moduleId = getModuleId(item); |
| boolean enabled = defaultDisabledModules == null || moduleId == null || !defaultDisabledModules.contains(moduleId); |
| if (item.getChecked() != enabled) { |
| item.setChecked(enabled); |
| providerModified = true; |
| } |
| } |
| } |
| |
| public void performOk() { |
| if (!providerModified) |
| return; |
| // save current selection |
| StringBuilder tmp = new StringBuilder(); |
| boolean first = true; |
| TableItem[] items = providerTable.getItems(); |
| for (TableItem item : items) { |
| if (item.getChecked()) { |
| continue; |
| } |
| if (!first) |
| tmp.append(','); |
| else |
| first = false; |
| tmp.append(((PasswordProviderDescription) item.getData()).getId()); |
| } |
| |
| IEclipsePreferences node = ConfigurationScope.INSTANCE.getNode(PREFERENCES_PLUGIN); |
| node.put(IStorageConstants.DISABLED_PROVIDERS_KEY, tmp.toString()); |
| |
| try { |
| node.flush(); |
| } catch (BackingStoreException e) { |
| // nothing can be done |
| } |
| |
| // logout so that previously selected default provider is not reused |
| InternalExchangeUtils.passwordProvidersReset(); |
| } |
| |
| public void onActivated() { |
| enableLogout(); |
| } |
| |
| protected void enableLogout() { |
| buttonClearPassword.setEnabled(InternalExchangeUtils.isLoggedIn()); |
| } |
| |
| protected void setButtonSize(Button button) { |
| GridDataFactory.defaultsFor(button).align(SWT.FILL, SWT.BEGINNING).grab(false, false).applyTo(button); |
| } |
| |
| protected boolean changePassword(ISecurePreferences node, String moduleID, String name, Shell shell) { |
| ReEncrypter reEncrypter = new ReEncrypter(node, moduleID); |
| if (!reEncrypter.decrypt()) { |
| MessageBox messageBox = new MessageBox(shell, SWT.YES | SWT.NO | SWT.ICON_WARNING); |
| messageBox.setText(SecUIMessages.changePasswordWizardTitle); |
| messageBox.setMessage(SecUIMessages.wizardDecodeWarning); |
| if (messageBox.open() == SWT.YES) |
| return false; |
| } |
| |
| if (!reEncrypter.switchToNewPassword()) { |
| MessageBox messageBox = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR); |
| messageBox.setText(SecUIMessages.changePasswordWizardTitle); |
| messageBox.setMessage(SecUIMessages.wizardSwitchError); |
| messageBox.open(); |
| return false; |
| } |
| reEncrypter.encrypt(); |
| |
| // all good |
| String msg = NLS.bind(SecUIMessages.passwordChangeDone, name); |
| MessageDialog.openInformation(StorageUtils.getShell(), SecUIMessages.generalDialogTitle, msg); |
| return true; |
| } |
| |
| protected void updateDescription() { |
| PasswordProviderDescription selectedModule = getSelectedModule(); |
| if (selectedModule != null && detailsText != null) |
| detailsText.setText(selectedModule.getDescription()); |
| } |
| |
| private HashSet<String> getDefaultDisabledModules() { |
| String defaultPreferenceValue = ""; //$NON-NLS-1$ |
| Preferences pluginNode = DefaultScope.INSTANCE.getNode(PREFERENCES_PLUGIN); |
| String tmp = pluginNode.get(IStorageConstants.DISABLED_PROVIDERS_KEY, defaultPreferenceValue); |
| HashSet<String> defaultDisabledModules = splitModuleIds(tmp); |
| return defaultDisabledModules; |
| } |
| |
| private String getModuleId(TableItem item) { |
| String moduleId = null; |
| Object itemData = item.getData(); |
| if (itemData instanceof PasswordProviderDescription) { |
| PasswordProviderDescription module = (PasswordProviderDescription) itemData; |
| moduleId = module.getId(); |
| } |
| return moduleId; |
| } |
| |
| private static HashSet<String> splitModuleIds(String joinedModuleIds) { |
| if (joinedModuleIds == null || joinedModuleIds.isEmpty()) |
| return null; |
| HashSet<String> modules = new HashSet<>(); |
| String[] disabledProviders = joinedModuleIds.split(","); //$NON-NLS-1$ |
| for (String disabledProvider : disabledProviders) { |
| modules.add(disabledProvider); |
| } |
| return modules; |
| } |
| } |