/* * Copyright (C) 2010 Marc A. Paradise * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.bbssh.ui.screens; import java.io.IOException; import java.util.Vector; import net.rim.device.api.crypto.CryptoTokenException; import net.rim.device.api.crypto.CryptoUnsupportedOperationException; import net.rim.device.api.crypto.DSAKeyPair; import net.rim.device.api.crypto.DSAPublicKey; import net.rim.device.api.crypto.InvalidKeyException; import net.rim.device.api.crypto.KeyPair; import net.rim.device.api.crypto.RSAKeyPair; import net.rim.device.api.i18n.ResourceBundleFamily; import net.rim.device.api.system.Clipboard; import net.rim.device.api.ui.ContextMenu; import net.rim.device.api.ui.Field; import net.rim.device.api.ui.MenuItem; import net.rim.device.api.ui.UiApplication; import net.rim.device.api.ui.component.Dialog; import net.rim.device.api.ui.component.ListField; import net.rim.device.api.ui.component.Menu; import net.rim.device.api.ui.component.Status; import net.rim.device.api.ui.container.MainScreen; import org.bbssh.crypto.SignatureTools; import org.bbssh.exceptions.KeyInUseException; import org.bbssh.help.HelpManager; import org.bbssh.i18n.BBSSHResource; import org.bbssh.model.Key; import org.bbssh.model.KeyManager; import org.bbssh.ui.components.VectorListFieldCallback; import org.bbssh.util.Tools; import ch.ethz.ssh2.crypto.PEMDecoder; /** * This screen allows the user to import keys from local storage, media card, http, or https locations. * * It will currently support * */ public final class KeyManagerScreen extends MainScreen implements BBSSHResource { ResourceBundleFamily res = ResourceBundleFamily.getBundle(BUNDLE_ID, BUNDLE_NAME); ListField keyListField = new ListField(); VectorListFieldCallback keyVector; private MenuItem importKey = new MenuItem(res, KEY_MGR_LABEL_IMPORT, 0x0010000, 10) { public void run() { handleAddKey(false); } }; private MenuItem generateKey = new MenuItem(res, KEY_MGR_LABEL_GENERATE, 0x0010000, 10) { public void run() { handleAddKey(true); } }; private MenuItem copyKeyToClipboard = new MenuItem(res, KEY_MGR_MENU_COPY_KEY, 0x0010000, 10) { public void run() { try { Key sel = getSelection(); if (sel == null) { return; } if (sel.isNativeKey()) { DSAPublicKey pk = sel.getKeyPair().getDSAPublicKey(); Clipboard.getClipboard().put(SignatureTools.exportPublicKey(pk)); } else { KeyPair kp = PEMDecoder.decode(sel.getData(), sel.getPassphrase()); if (kp instanceof DSAKeyPair) { Clipboard.getClipboard().put(SignatureTools.exportPublicKey(((DSAKeyPair)kp).getDSAPublicKey())); } else if (kp instanceof RSAKeyPair) { Clipboard.getClipboard().put(SignatureTools.exportPublicKey(((RSAKeyPair)kp).getRSAPublicKey())); } } Status.show(res.getString(MSG_KEY_COPIED_TO_CLIP)); } catch (InvalidKeyException ex) { Status.show("Provided key is a not a valid key."); } catch (IOException ex) { Status.show(ex.getMessage() + " : " + ex.toString()); // @todo some error handlign here would be nice. } catch (IllegalArgumentException ex) { Status.show(ex.getMessage() + " : " + ex.toString()); // @todo prompt for correct password - this one was blank // but none is provided. } catch (CryptoTokenException e) { Status.show(e.getMessage() + " : " + e.toString()); // @todo some error handlign here would be nice. } catch (CryptoUnsupportedOperationException e) { Status.show(e.getMessage() + " : " + e.toString()); // @todo some error handlign here would be nice. } } }; private MenuItem deleteKey = new MenuItem(res, KEY_MGR_MENU_DEL_KEY, 10000, 10) { public void run() { if (Dialog.ask(Dialog.D_DELETE, res.getString(MSG_CONFIRM_DELETE), Dialog.DELETE) != Dialog.DELETE) { return; } KeyManager m = KeyManager.getInstance(); Key key = getSelection(); if (key == null) { return; } try { m.deleteKey(key); keyListField.setSize(m.getKeys().size()); keyListField.invalidate(); } catch (KeyInUseException ex) { Status.show(res.getString(MSG_KEY_IN_USE)); } } }; // private MenuItem refreshKey = new MenuItem(res, KEY_MGR_MENU_REFRESH, // 10000, 10) { // public void run() { // // @todo unimplemented // // keyListField.setSize(m.getKeys().size()); // // keyListField.invalidate(); // } // }; // private MenuItem editKey = new MenuItem(res, KEY_MGR_MENU_EDIT, 10000, 10) { // public void run() { // // @todo unimplemented // // keyListField.setSize(m.getKeys().size()); // // keyListField.invalidate(); // } // }; /** * Instantiates a new key manager screen. */ public KeyManagerScreen() { super(0); setTitle(res.getString(KEY_MGR_TITLE)); Vector v = KeyManager.getInstance().getKeys(); keyVector = new VectorListFieldCallback(v); // Old versions are unsorted - fix that here. Tools.sortVector(v); keyListField.setCallback(keyVector); keyListField.setEmptyString(res, KEY_MGR_EMPTY_LIST_TEXT, 0); keyListField.setSize(v.size()); setTitle(res, KEY_MGR_TITLE); add(keyListField); } /** * Gets the selection. * * @return the selection */ private Key getSelection() { int x = keyListField.getSelectedIndex(); if (x == -1) { return null; } Object o = keyVector.get(keyListField, x); if (!(o instanceof Key)) { return null; } Key k = (Key) o; if (k.getId() == Key.INVALID_ID) { k = null; } return k; } /** * Create context menu. * * @param contextMenu the context menu */ protected void makeContextMenu(ContextMenu contextMenu) { super.makeContextMenu(contextMenu); Field focusField = contextMenu.getTarget(); // We only want to provide a special context menu for our // list of keys if (focusField != keyListField) { return; } Key key = getSelection(); if (key == null) { return; } // contextMenu.addItem(this.editKey); contextMenu.addItem(this.copyKeyToClipboard); // contextMenu.addItem(this.refreshKey); contextMenu.addItem(this.deleteKey); contextMenu.setDefaultItem(copyKeyToClipboard); } /** * Create screen menu. * * @param menu the menu * @param instance the instance */ protected void makeMenu(Menu menu, int instance) { menu.add(HelpManager.getHelpMenu()); super.makeMenu(menu, instance); menu.add(this.importKey); menu.add(this.generateKey); Key key = getSelection(); if (key == null) { return; } // menu.add(this.editKey); menu.add(this.copyKeyToClipboard); // menu.add(this.refreshKey); menu.add(this.deleteKey); menu.setDefault(copyKeyToClipboard); } public void close() { KeyManager.getInstance().commitData(); super.close(); } /* * (non-Javadoc) * * @see net.rim.device.api.ui.Screen#isDirty() */ public boolean isDirty() { return true; } /* * (non-Javadoc) * * @see net.rim.device.api.ui.container.MainScreen#onSavePrompt() */ protected boolean onSavePrompt() { return true; } /** * Handle add key. * * @param indicates whether this is to be a new key or not. */ private void handleAddKey(boolean generateNew) { ImportKeyScreen s = new ImportKeyScreen(generateNew); UiApplication.getUiApplication().pushModalScreen(s); Key k = s.getKey(); KeyManager km = KeyManager.getInstance(); if (k != null) { km.addKey(k); Vector keys = km.getKeys(); Tools.sortVector(keys); keyListField.setSize(keys.size()); keyListField.invalidate(); } } }