/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.motorolamobility.studio.android.certmanager.ui.dialogs.importks; import java.io.File; import java.security.KeyStore.Entry; import java.security.KeyStore.PasswordProtection; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.dialogs.TitleAreaDialog; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.CheckboxTableViewer; import org.eclipse.jface.viewers.ColumnLabelProvider; import org.eclipse.jface.viewers.ColumnViewer; import org.eclipse.jface.viewers.EditingSupport; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.viewers.TextCellEditor; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.PlatformUI; import com.motorola.studio.android.common.log.StudioLogger; import com.motorolamobility.studio.android.certmanager.CertificateManagerActivator; import com.motorolamobility.studio.android.certmanager.core.KeyStoreManager; import com.motorolamobility.studio.android.certmanager.exception.InvalidPasswordException; import com.motorolamobility.studio.android.certmanager.exception.KeyStoreManagerException; import com.motorolamobility.studio.android.certmanager.i18n.CertificateManagerNLS; import com.motorolamobility.studio.android.certmanager.ui.model.IKeyStore; public class ImportEntriesDialog extends TitleAreaDialog { public class EntryModel { private final String alias; private String passwd; private boolean verified; public EntryModel(String alias) { this.alias = alias; try { String savedPass = sourceKeyStore.getPasswordProvider().getPassword(alias, false); setPasswd(savedPass != null ? savedPass : ""); //$NON-NLS-1$ } catch (KeyStoreManagerException e) { setPasswd(""); //$NON-NLS-1$ } } @Override public String toString() { return alias; } public String getPasswd() { return passwd; } public void setPasswd(String passwd) { this.passwd = passwd; try { Entry entry = sourceKeyStore.getKeyStore().getEntry(alias, new PasswordProtection(passwd.toCharArray())); setVerified(entry != null); } catch (Exception e) { setVerified(false); } aliasMap.put(alias, passwd); } public String getAlias() { return alias; } public boolean isVerified() { return verified; } private void setVerified(boolean verified) { this.verified = verified; // entriesTableViewer.update(this, null); validateUi(); } } public class EntriesContentProvider implements IStructuredContentProvider { @Override public void dispose() { //do nothing } @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { validateUi(); } @Override public Object[] getElements(Object inputElement) { List<EntryModel> modelList = null; if (inputElement instanceof List<?>) { List<?> inputList = (List<?>) inputElement; modelList = new ArrayList<EntryModel>(inputList.size()); Iterator<?> it = inputList.iterator(); while (it.hasNext()) { Object element = it.next(); if (element instanceof String) //received an alias { String alias = (String) element; EntryModel entryModel = new EntryModel(alias); modelList.add(entryModel); } } } return modelList.toArray(); } } private final class PasswordEditingSupport extends EditingSupport { private PasswordEditingSupport(ColumnViewer viewer) { super(viewer); } @Override protected boolean canEdit(Object element) { return true; } @Override protected CellEditor getCellEditor(Object element) { return new TextCellEditor(entriesTable, SWT.PASSWORD); } @Override protected Object getValue(Object element) { return ((EntryModel) element).getPasswd(); } @Override protected void setValue(Object element, Object value) { EntryModel model = (EntryModel) element; model.setPasswd((String) value); getViewer().update(element, null); } } private static final String WIZARD_BANNER = "icons/wizban/import_entries_wiz.png"; //$NON-NLS-1$ private static final String HELP_ID = CertificateManagerActivator.PLUGIN_ID + ".import_entries_dialog"; //$NON-NLS-1$ private IKeyStore sourceKeyStore; private IKeyStore targetKeyStore; private Text passwdText; protected String sourcePassword = ""; //$NON-NLS-1$ private Table entriesTable; private CheckboxTableViewer entriesTableViewer; private final Map<String, String> aliasMap = new HashMap<String, String>(); private Combo keyStoreCombo; private Combo targetKsCombo; protected List<String> selectedAlias = new ArrayList<String>(); /** * Create the dialog. * @param parentShell */ public ImportEntriesDialog(Shell parentShell, IKeyStore keyStore) { super(parentShell); setShellStyle(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL); this.targetKeyStore = keyStore; setTitleImage(CertificateManagerActivator.imageDescriptorFromPlugin( CertificateManagerActivator.PLUGIN_ID, WIZARD_BANNER).createImage()); } /** * Create contents of the dialog. * @param parent */ @Override protected Control createDialogArea(Composite parent) { parent.getShell().setText(CertificateManagerNLS.ImportKeyStoreDialog_Dialog_Title); setMessage(CertificateManagerNLS.ImportKeyStoreDialog_Default_Message); setTitle(CertificateManagerNLS.ImportKeyStoreDialog_Dialog_Title); Composite area = (Composite) super.createDialogArea(parent); Composite container = new Composite(area, SWT.NONE); container.setLayout(new GridLayout(1, false)); container.setLayoutData(new GridData(GridData.FILL_BOTH)); Group SourceGroup = new Group(container, SWT.NONE); SourceGroup.setText(CertificateManagerNLS.ImportKeyStoreDialog_Source_Group); SourceGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); SourceGroup.setLayout(new GridLayout(1, false)); Composite keyStoreComposite = new Composite(SourceGroup, SWT.NONE); keyStoreComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1)); keyStoreComposite.setLayout(new GridLayout(3, false)); Label keyStoreLabel = new Label(keyStoreComposite, SWT.NONE); keyStoreLabel.setText(CertificateManagerNLS.ImportKeyStoreDialog_KeyStore_Label); keyStoreCombo = new Combo(keyStoreComposite, SWT.READ_ONLY); keyStoreCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1)); Label passwdLabel = new Label(keyStoreComposite, SWT.NONE); passwdLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); passwdLabel.setText(CertificateManagerNLS.ImportKeyStoreDialog_Password_Label); passwdText = new Text(keyStoreComposite, SWT.BORDER | SWT.PASSWORD); passwdText.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { sourcePassword = passwdText.getText(); } }); passwdText.addSelectionListener(new SelectionAdapter() { @Override public void widgetDefaultSelected(SelectionEvent e) { super.widgetDefaultSelected(e); loadEntries(); } }); passwdText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); Button loadButton = new Button(keyStoreComposite, SWT.NONE); GridData gd_loadButton = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1); gd_loadButton.widthHint = 80; loadButton.setLayoutData(gd_loadButton); loadButton.setText(CertificateManagerNLS.ImportKeyStoreDialog_Load_Button); Composite entriesComposite = new Composite(SourceGroup, SWT.NONE); GridData gd_entriesComposite = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1); gd_entriesComposite.heightHint = 200; entriesComposite.setLayoutData(gd_entriesComposite); entriesComposite.setLayout(new GridLayout(1, true)); entriesTableViewer = CheckboxTableViewer.newCheckList(entriesComposite, SWT.BORDER | SWT.CHECK | SWT.FULL_SELECTION); entriesTableViewer.setContentProvider(new EntriesContentProvider()); entriesTable = entriesTableViewer.getTable(); entriesTable.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (e.detail == SWT.CHECK) { validateUi(); TableItem item = (TableItem) e.item; if (item.getChecked()) { selectedAlias.add(item.getText(0)); } else { selectedAlias.remove(item.getText(0)); } } } }); entriesTable.setHeaderVisible(true); GridData gd_entriesTable = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1); gd_entriesTable.heightHint = 250; entriesTable.setLayoutData(gd_entriesTable); TableViewerColumn aliasViewerColumn = new TableViewerColumn(entriesTableViewer, SWT.NONE); TableColumn tblclmnAlias = aliasViewerColumn.getColumn(); tblclmnAlias.setWidth(100); tblclmnAlias.setText(CertificateManagerNLS.ImportKeyStoreDialog_Alias_Column); aliasViewerColumn.setLabelProvider(new ColumnLabelProvider() { @Override public String getText(Object element) { return ((EntryModel) element).getAlias(); } }); TableViewerColumn passwordViewerColumn_1 = new TableViewerColumn(entriesTableViewer, SWT.NONE); passwordViewerColumn_1.setEditingSupport(new PasswordEditingSupport(entriesTableViewer)); TableColumn tblclmnPassword = passwordViewerColumn_1.getColumn(); tblclmnPassword.setWidth(100); tblclmnPassword.setText(CertificateManagerNLS.ImportKeyStoreDialog_Passwd_Column); passwordViewerColumn_1.setLabelProvider(new ColumnLabelProvider() { @Override public String getText(Object element) { return ((EntryModel) element).getPasswd().replaceAll(".", "*"); //$NON-NLS-1$ //$NON-NLS-2$ } }); TableViewerColumn verifiedViewerColumn_2 = new TableViewerColumn(entriesTableViewer, SWT.NONE); TableColumn tblclmnVerified = verifiedViewerColumn_2.getColumn(); tblclmnVerified.setWidth(130); tblclmnVerified.setText(CertificateManagerNLS.ImportKeyStoreDialog_Verified_Column); verifiedViewerColumn_2.setLabelProvider(new ColumnLabelProvider() { @Override public String getText(Object element) { return ((EntryModel) element).isVerified() ? CertificateManagerNLS.ImportKeyStoreDialog_Verified_Pass_Yes : CertificateManagerNLS.ImportKeyStoreDialog_Verified_Pass_Wrong; } }); loadButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { loadEntries(); } }); keyStoreCombo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { super.widgetSelected(e); sourceKeyStore = (IKeyStore) keyStoreCombo.getData(keyStoreCombo.getText()); IKeyStore keyStore = (IKeyStore) keyStoreCombo.getData(keyStoreCombo.getText()); try { sourcePassword = keyStore.getPasswordProvider().getKeyStorePassword(false); } catch (KeyStoreManagerException e1) { StudioLogger.error("Error while accessing keystore manager. " + e1.getMessage()); } if (sourcePassword == null) { sourcePassword = ""; //$NON-NLS-1$ } passwdText.setText(sourcePassword); loadEntries(); updateTargetCombo(); validateUi(); } }); Group targetGroup = new Group(container, SWT.NONE); targetGroup.setLayout(new GridLayout(2, false)); targetGroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); targetGroup.setText(CertificateManagerNLS.ImportKeyStoreDialog_Target_Group); Label targetKsLabel = new Label(targetGroup, SWT.NONE); targetKsLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); targetKsLabel.setText(CertificateManagerNLS.ImportKeyStoreDialog_KeyStore_Label); targetKsCombo = new Combo(targetGroup, SWT.READ_ONLY); targetKsCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); targetKsCombo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { super.widgetSelected(e); String selectedItem = targetKsCombo.getText(); targetKeyStore = (IKeyStore) targetKsCombo.getData(selectedItem); validateUi(); } }); final KeyStoreManager keyStoreManager = KeyStoreManager.getInstance(); try { List<IKeyStore> keyStores = keyStoreManager.getKeyStores(); for (IKeyStore keyStore : keyStores) { File ksFile = keyStore.getFile(); String comboItem = ksFile.getName() + " - " + ksFile.getAbsolutePath(); //$NON-NLS-1$ keyStoreCombo.add(comboItem); keyStoreCombo.setData(comboItem, keyStore); if (keyStore.equals(this.sourceKeyStore)) { keyStoreCombo.select(keyStoreCombo.indexOf(comboItem)); } else { targetKsCombo.add(comboItem); targetKsCombo.setData(comboItem, keyStore); if (keyStore.equals(this.targetKeyStore)) { targetKsCombo.select(targetKsCombo.indexOf(comboItem)); } } } } catch (KeyStoreManagerException e1) { setErrorMessage(CertificateManagerNLS.ImportKeyStoreDialog_Error_Loading_Keystores); } return area; } @Override protected Control createHelpControl(Composite parent) { PlatformUI.getWorkbench().getHelpSystem().setHelp(parent.getShell(), HELP_ID); return super.createHelpControl(parent); } private void updateTargetCombo() { final KeyStoreManager keyStoreManager = KeyStoreManager.getInstance(); try { targetKsCombo.clearSelection(); targetKsCombo.setItems(new String[0]); List<IKeyStore> keyStores = keyStoreManager.getKeyStores(); for (IKeyStore keyStore : keyStores) { if (keyStore != this.sourceKeyStore) { File ksFile = keyStore.getFile(); String comboItem = ksFile.getName() + " - " + ksFile.getAbsolutePath(); //$NON-NLS-1$ targetKsCombo.add(comboItem); targetKsCombo.setData(comboItem, keyStore); if (keyStore.equals(targetKeyStore)) { targetKsCombo.select(targetKsCombo.indexOf(comboItem)); } } } if (targetKsCombo.getSelectionIndex() == -1) //nothing is selected. { targetKeyStore = null; } } catch (KeyStoreManagerException e1) { setErrorMessage(CertificateManagerNLS.ImportKeyStoreDialog_Error_Loading_Keystores); } } private void loadEntries() { try { aliasMap.clear(); if (!sourcePassword.isEmpty()) { List<String> aliases = sourceKeyStore.getAliases(sourcePassword); entriesTableViewer.setInput(aliases); } else { entriesTableViewer.setInput(new ArrayList<String>()); } } catch (KeyStoreManagerException e1) { setErrorMessage(CertificateManagerNLS.ImportKeyStoreDialog_Error_Loading_Entries); entriesTableViewer.setInput(new ArrayList<String>()); } catch (InvalidPasswordException e1) { setErrorMessage(CertificateManagerNLS.ImportKeyStoreDialog_Invalid_Keystore_Passwd); entriesTableViewer.setInput(new ArrayList<String>()); } } @Override protected Control createButtonBar(Composite parent) { Control bar = super.createButtonBar(parent); getButton(OK).setEnabled(false); return bar; } public void validateUi() { boolean isValid = true; setErrorMessage(null); if (isValid && (sourceKeyStore == null)) { isValid = false; setMessage(CertificateManagerNLS.ImportKeyStoreDialog_Select_Source_Ks); } if (isValid && ((sourcePassword == null) || sourcePassword.isEmpty())) { isValid = false; setMessage(CertificateManagerNLS.ImportKeyStoreDialog_Type_SourceKs_Passwd); } if (isValid) { try { if (!sourceKeyStore.isPasswordValid(sourcePassword)) { isValid = false; setErrorMessage("Wrong source keystore password."); } } catch (KeyStoreManagerException e) { isValid = false; setErrorMessage("Unable to access source keystore.\n" + e.getMessage()); } catch (InvalidPasswordException e) { isValid = false; setErrorMessage("Wrong source keystore password."); } } if (isValid) { List<?> input = (List<?>) entriesTableViewer.getInput(); if (input != null) { int itemCount = input.size(); if (itemCount == 0) { isValid = false; setMessage(CertificateManagerNLS.ImportKeyStoreDialog_No_Entries_To_Import, IMessageProvider.WARNING); } if (entriesTableViewer.getCheckedElements().length == 0) { isValid = false; setMessage(CertificateManagerNLS.ImportKeyStoreDialog_No_Entries_To_Import, IMessageProvider.WARNING); } else { for (int i = 0; i < itemCount; i++) { EntryModel entryModel = (EntryModel) entriesTableViewer.getElementAt(i); if (entriesTableViewer.getChecked(entryModel) && !entryModel.isVerified()) { isValid = false; setMessage( CertificateManagerNLS.ImportKeyStoreDialog_Wrong_Entries_Passwd, IMessageProvider.WARNING); break; } } } } else { isValid = false; setMessage(CertificateManagerNLS.ImportKeyStoreDialog_No_Entries_To_Import, IMessageProvider.WARNING); } } if (isValid && (targetKeyStore == null)) { isValid = false; setMessage(CertificateManagerNLS.ImportKeyStoreDialog_Select_Target_Kesytore); } if (!isValid) { getButton(OK).setEnabled(false); } else { getButton(OK).setEnabled(true); setErrorMessage(null); setMessage(CertificateManagerNLS.ImportKeyStoreDialog_Default_Message); } } public IKeyStore getKeyStore() { return sourceKeyStore; } public Map<String, String> getAliases() { Map<String, String> selectedAliasMap = new HashMap<String, String>(selectedAlias.size()); for (String alias : selectedAlias) { selectedAliasMap.put(alias, aliasMap.get(alias)); } return selectedAliasMap; } public IKeyStore getTargetKeyStore() { return targetKeyStore; } public String getPassword() { return sourcePassword; } }