diff options
Diffstat (limited to 'src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/core/PasswordProvider.java')
-rw-r--r-- | src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/core/PasswordProvider.java | 484 |
1 files changed, 484 insertions, 0 deletions
diff --git a/src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/core/PasswordProvider.java b/src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/core/PasswordProvider.java new file mode 100644 index 0000000..ce73f09 --- /dev/null +++ b/src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/core/PasswordProvider.java @@ -0,0 +1,484 @@ +/* + * 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.core; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import org.eclipse.equinox.security.storage.ISecurePreferences; +import org.eclipse.equinox.security.storage.SecurePreferencesFactory; +import org.eclipse.equinox.security.storage.StorageException; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.PlatformUI; + +import com.motorola.studio.android.common.log.StudioLogger; +import com.motorola.studio.android.common.utilities.EclipseUtils; +import com.motorolamobility.studio.android.certmanager.CertificateManagerActivator; +import com.motorolamobility.studio.android.certmanager.exception.KeyStoreManagerException; +import com.motorolamobility.studio.android.certmanager.i18n.CertificateManagerNLS; + +/** + * This class is responsible to retrieve passwords for a keystore and its entries. + * Usage: + * Instantiate with a keyStoreFile, call the methods getPassword. + * If needed a dialog will be shown, asking user to type the password. + */ +public class PasswordProvider +{ + + private static final String PREF_ROOT_NODE = CertificateManagerActivator.PLUGIN_ID + + "_passwords"; //$NON-NLS-1$ + + private static final String KS_PASSWORD_KEY = "KS_PASSWORD"; //$NON-NLS-1$ + + private final class KeyStorePasswdDialog extends Dialog + { + private final File keyStoreFile; + + private String passwd; + + private boolean savePasswd; + + private Text paswordText; + + private Button saveCheckBox; + + private final String alias; + + private KeyStorePasswdDialog(Shell parentShell, File keyStoreFile, String alias) + { + super(parentShell); + this.keyStoreFile = keyStoreFile; + this.alias = alias; + } + + @Override + protected Control createDialogArea(Composite parent) + { + + Composite mainComposite = new Composite(parent, SWT.NONE); + GridLayout gridLayout = new GridLayout(2, false); + mainComposite.setLayout(gridLayout); + + //Creates the message + Label messageLabel = new Label(mainComposite, SWT.NONE); + GridData gridData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 2); + messageLabel.setLayoutData(gridData); + + if (this.alias.equals(KS_PASSWORD_KEY)) + { + getShell().setText(CertificateManagerNLS.PasswordProvider_DialogTitle); + messageLabel.setText(NLS.bind(CertificateManagerNLS.PasswordProvider_MessageLabel, + keyStoreFile.getName())); + } + else + { + getShell().setText(CertificateManagerNLS.CertificateBlock_KeyPassword_Label); + messageLabel.setText(NLS.bind( + CertificateManagerNLS.PasswordProvider_Key_MessageLabel, alias)); + } + + //Creates the text field label + Label passwdLabel = new Label(mainComposite, SWT.NONE); + gridData = new GridData(SWT.LEFT, SWT.CENTER, false, false); + passwdLabel.setLayoutData(gridData); + passwdLabel.setText(CertificateManagerNLS.PasswordProvider_PasswordLabel); + + //Creates the password text + paswordText = new Text(mainComposite, SWT.BORDER | SWT.PASSWORD); + gridData = new GridData(SWT.FILL, SWT.CENTER, true, false); + paswordText.setLayoutData(gridData); + + //Creates the save password checkbox + saveCheckBox = new Button(mainComposite, SWT.CHECK); + saveCheckBox.setText(CertificateManagerNLS.PasswordProvider_SaveThisPassword); + saveCheckBox.setSelection(false); + gridData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1); + saveCheckBox.setLayoutData(gridData); + saveCheckBox.setVisible(KeyStoreManager.getInstance().isKeystoreMapped(keyStoreFile)); + + return super.createDialogArea(parent); + } + + @Override + protected void okPressed() + { + passwd = paswordText.getText(); + savePasswd = saveCheckBox.getSelection(); + super.okPressed(); + } + + public String getPasswd() + { + return passwd; + } + + public boolean mustSavePasswd() + { + return savePasswd; + } + } + + private final File keyStoreFile; + + private final ISecurePreferences securePreferences; + + private boolean canSavePassword = true; + + public PasswordProvider(File keyStoreFile) + { + this(keyStoreFile, KeyStoreManager.getInstance().isKeystoreMapped(keyStoreFile)); + } + + public PasswordProvider(File keyStoreFile, boolean canSavePassword) + { + this.keyStoreFile = keyStoreFile; + this.securePreferences = SecurePreferencesFactory.getDefault(); + this.canSavePassword = canSavePassword; + } + + /** + * Retrieves the KeyStore password. + * @param promptPassword whether the password entry dialog will be shown or not + * @param useSavedPassword whether to use the keyStore saved password + * @return the password string or null if user canceled the dialog + * @throws KeyStoreManagerException + */ + public String getKeyStorePassword(boolean promptPassword, boolean useSavedPassword) + throws KeyStoreManagerException + { + return getPassword(KS_PASSWORD_KEY, promptPassword, useSavedPassword); + } + + /** + * Retrieves the KeyStore password. + * This method will always attempt to retrieve the saved password. + * It's behavior is the same as of calling the method getPassword(promptPassword, true) + * @param promptPassword whether the password entry dialog will be shown or not + * @return the password string or null if user canceled the dialog + * @throws KeyStoreManagerException + */ + public String getKeyStorePassword(boolean promptPassword) throws KeyStoreManagerException + { + return getPassword(KS_PASSWORD_KEY, promptPassword, true); + } + + /** + * Retrieves the password for a given alias within a keyStore. + * This method will always attempt to retrieve the saved password. + * It's behavior is the same as of calling the method getPassword(promptPassword, true) + * @param promptPassword whether the password entry dialog will be shown or not + * @return the password string or null if user canceled the dialog + * @throws KeyStoreManagerException + */ + public String getPassword(String alias, boolean promptPassword) throws KeyStoreManagerException + { + return getPassword(alias, promptPassword, true); + } + + /** + * Retrieves the password for a given alias within a keyStore. + * This method will always attempt to retrieve the saved password. + * It's behavior is the same as of calling the method getPassword(promptPassword, true) + * @param promptPassword whether the password entry dialog will be shown or not + * @param useSavedPassword whether to use the keyStore saved password + * @return the password string or null if user canceled the dialog + * @throws KeyStoreManagerException + */ + public String getPassword(String alias, boolean promptPassword, boolean useSavedPassword) + throws KeyStoreManagerException + { + String password = null; + + if (useSavedPassword) + { + if (securePreferences != null) + { + String prefKey = alias; + password = getSavedPasswd(prefKey); + } + else + { + throw new KeyStoreManagerException( + CertificateManagerNLS.PasswordProvider_Error_WhileSaving); + } + } + + if ((password == null) && promptPassword) + { + password = promptPassword(alias); + } + + return password; + } + + private String getSavedPasswd(String prefKey) + { + String password = null; + // Try to get the password from secure storage + if (securePreferences.nodeExists(PREF_ROOT_NODE)) + { + ISecurePreferences node = securePreferences.node(PREF_ROOT_NODE); + try + { + if (node.nodeExists(keyStoreFile.getAbsolutePath())) + { + ISecurePreferences ksNode = node.node(keyStoreFile.getAbsolutePath()); + password = ksNode.get(prefKey, null); + } + } + catch (StorageException e) + { + //Do nothing, password will be null. + } + } + return password; + } + + private String promptPassword(final String alias) throws KeyStoreManagerException + { + final String[] result = new String[1]; + final Boolean[] canProceed = new Boolean[1]; + + Display.getDefault().syncExec(new Runnable() + { + @Override + public void run() + { + KeyStorePasswdDialog dialog = + new KeyStorePasswdDialog(PlatformUI.getWorkbench() + .getModalDialogShellProvider().getShell(), keyStoreFile, alias); + + int diagStatus = dialog.open(); + + if (diagStatus == Dialog.OK) + { + //Read the values from the dialog and do the actions, return passwd and save if required + result[0] = dialog.getPasswd(); + + canSavePassword = KeyStoreManager.getInstance().isKeystoreMapped(keyStoreFile); + canProceed[0] = dialog.mustSavePasswd(); + } + else + { + //dialog cancelled + canProceed[0] = false; + result[0] = null; + } + } + }); + + if (canProceed[0] && canSavePassword) + { + if (securePreferences != null) + { + savePassword(alias, result[0]); + } + else + { + EclipseUtils.showWarningDialog(CertificateManagerNLS.PasswordProvider_DialogTitle, + CertificateManagerNLS.PasswordProvider_Error_WhileSaving); + } + } + + return result[0]; + } + + public void saveKeyStorePassword(String password) throws KeyStoreManagerException + { + savePassword(KS_PASSWORD_KEY, password); + } + + public void savePassword(final String alias, String password) throws KeyStoreManagerException + { + String prefKey; + canSavePassword = KeyStoreManager.getInstance().isKeystoreMapped(keyStoreFile); + if (canSavePassword) //protect from saving + { + if (alias != null) + { + prefKey = alias; + } + else + { + prefKey = KS_PASSWORD_KEY; + } + + ISecurePreferences rootNode = securePreferences.node(PREF_ROOT_NODE); + try + { + ISecurePreferences ksNode = rootNode.node(keyStoreFile.getAbsolutePath()); + ksNode.put(prefKey, password, true); + ksNode.flush(); + } + catch (Exception e) + { + throw new KeyStoreManagerException( + CertificateManagerNLS.PasswordProvider_Error_WhileSaving); + } + } + } + + /** + * Deletes the entire node (including KS_PASSWORD_KEY and children aliases) + * @throws KeyStoreManagerException + */ + public void deleteKeyStoreSavedPasswordNode() throws KeyStoreManagerException + { + deleteSavedPassword(null); + } + + /** + * Deletes only KS_PASSWORD_KEY (not children aliases) + */ + public void deleteKeyStoreSavedPassword() throws KeyStoreManagerException + { + deleteSavedPassword(KS_PASSWORD_KEY); + } + + public void deleteSavedPassword(String alias) throws KeyStoreManagerException + { + + ISecurePreferences ksNode = getKeyStoreNode(); + if (ksNode != null) + { + if (alias == null) + { + ksNode.removeNode(); + } + else + { + ksNode.remove(alias); + //if no item has no child, then we can remove the node + if (ksNode.keys().length == 0) + { + ksNode.removeNode(); + } + } + + try + { + ksNode.flush(); + } + catch (IllegalStateException e) + { + //Do nothing, node has already been removed + } + catch (IOException e) + { + throw new KeyStoreManagerException(NLS.bind( + CertificateManagerNLS.PasswordProvider_Error_WhileRemovingPassword, + keyStoreFile.getName())); + } + } + } + + /** + * This method will remove all saved entries for this keystore file that is not listed on the aliasList. + * The idea is to remove all saved passwords that makes reference to non-existant entries. + * @param aliasList the list of alias to be kept if available on the security keystore + * @throws KeyStoreManagerException if writing the security keystore fails for some reason + */ + public void cleanModel(List<String> aliasList) throws KeyStoreManagerException + { + ISecurePreferences keyStoreNode = getKeyStoreNode(); + if (keyStoreNode != null) + { + String[] savedKeys = keyStoreNode.keys(); + for (String savedAlias : savedKeys) + { + if (!savedAlias.equals(KS_PASSWORD_KEY) && !aliasList.contains(savedAlias)) + { + keyStoreNode.remove(savedAlias); + } + } + try + { + keyStoreNode.flush(); + } + catch (IOException e) + { + throw new KeyStoreManagerException(NLS.bind( + CertificateManagerNLS.PasswordProvider_Error_WhileRemovingPassword, + keyStoreFile.getName())); + } + } + } + + /* + * @return the keystore node if it exists + */ + private ISecurePreferences getKeyStoreNode() + { + ISecurePreferences ksNode = null; + if (securePreferences.nodeExists(PREF_ROOT_NODE)) + { + ISecurePreferences rootNode = securePreferences.node(PREF_ROOT_NODE); + + if (rootNode.nodeExists(keyStoreFile.getAbsolutePath())) + { + ksNode = rootNode.node(keyStoreFile.getAbsolutePath()); + } + } + return ksNode; + } + + /** + * If keystore password is saved. + */ + public boolean isPasswordSaved() + { + return isPasswordSaved(KS_PASSWORD_KEY); + } + + /** + * If alias password is saved. + */ + public boolean isPasswordSaved(String prefKey) + { + ISecurePreferences ksNode = null; + boolean isSaved = false; + if (securePreferences.nodeExists(PREF_ROOT_NODE)) + { + ISecurePreferences rootNode = securePreferences.node(PREF_ROOT_NODE); + ksNode = rootNode.node(keyStoreFile.getAbsolutePath()); + try + { + String value = ksNode.get(prefKey, null); + isSaved = value != null; //password is saved if it is not the default value (because password length should be at least 6 + } + catch (StorageException e) + { + StudioLogger.debug("It was not possible to get if the " + prefKey + + " is saved or not"); + isSaved = false; + } + } + return isSaved; + } +} |