| /******************************************************************************* |
| * Copyright (c) 2008 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.equinox.internal.security.storage; |
| |
| import java.io.*; |
| import java.net.URL; |
| import java.util.*; |
| import javax.crypto.spec.PBEKeySpec; |
| import org.eclipse.equinox.internal.security.auth.AuthPlugin; |
| import org.eclipse.equinox.internal.security.auth.nls.SecAuthMessages; |
| import org.eclipse.equinox.security.storage.ISecurePreferences; |
| import org.eclipse.equinox.security.storage.provider.IProviderHints; |
| import org.eclipse.osgi.framework.log.FrameworkLogEntry; |
| import org.eclipse.osgi.service.environment.EnvironmentInfo; |
| import org.eclipse.osgi.util.NLS; |
| |
| public class SecurePreferencesMapper { |
| |
| /** |
| * Command line argument specifying default location |
| */ |
| final private static String KEYRING_ARGUMENT = "-eclipse.keyring"; //$NON-NLS-1$ |
| |
| /** |
| * Command line argument specifying default password |
| */ |
| final private static String PASSWORD_ARGUMENT = "-eclipse.password"; //$NON-NLS-1$ |
| |
| static private ISecurePreferences defaultPreferences = null; |
| |
| static private Map preferences = new HashMap(); // URL.toString() -> SecurePreferencesRoot |
| |
| static public ISecurePreferences getDefault() { |
| if (defaultPreferences == null) { |
| try { |
| defaultPreferences = open(null, null); |
| } catch (IOException e) { |
| AuthPlugin.getDefault().logError(SecAuthMessages.keyringNotAvailable, e); |
| } |
| } |
| return defaultPreferences; |
| } |
| |
| static public void clearDefault() { |
| if (defaultPreferences == null) |
| return; |
| |
| try { |
| defaultPreferences.flush(); |
| } catch (IOException e) { |
| // ignore in this context |
| } |
| close((((SecurePreferencesWrapper) defaultPreferences).getContainer().getRootData())); |
| defaultPreferences = null; |
| } |
| |
| static public ISecurePreferences open(URL location, Map options) throws IOException { |
| // 1) find if there are any command line arguments that need to be added |
| EnvironmentInfo infoService = AuthPlugin.getDefault().getEnvironmentInfoService(); |
| if (infoService != null) { |
| String[] args = infoService.getNonFrameworkArgs(); |
| if (args != null && args.length != 0) { |
| for (int i = 0; i < args.length - 1; i++) { |
| if (args[i + 1].startsWith(("-"))) //$NON-NLS-1$ |
| continue; |
| if (location == null && KEYRING_ARGUMENT.equalsIgnoreCase(args[i])) { |
| location = new File(args[i + 1]).toURL(); // don't use File.toURI().toURL() |
| continue; |
| } |
| if (PASSWORD_ARGUMENT.equalsIgnoreCase(args[i])) { |
| options = processPassword(options, args[i + 1]); |
| continue; |
| } |
| } |
| } |
| } |
| |
| // 2) process location |
| if (location == null) |
| location = StorageUtils.getDefaultLocation(); |
| if (!StorageUtils.isFile(location)) |
| // at this time we only accept file URLs; check URL type right away |
| throw new IOException(NLS.bind(SecAuthMessages.loginFileURL, location.toString())); |
| |
| // 3) see if there is already SecurePreferencesRoot at that location; if not open a new one |
| String key = location.toString(); |
| SecurePreferencesRoot root; |
| if (preferences.containsKey(key)) |
| root = (SecurePreferencesRoot) preferences.get(key); |
| else { |
| root = new SecurePreferencesRoot(location); |
| preferences.put(key, root); |
| } |
| |
| // 4) create container with the options passed in |
| SecurePreferencesContainer container = new SecurePreferencesContainer(root, options); |
| return container.getPreferences(); |
| } |
| |
| static public void stop() { |
| synchronized (preferences) { |
| for (Iterator i = preferences.values().iterator(); i.hasNext();) { |
| SecurePreferencesRoot provider = (SecurePreferencesRoot) i.next(); |
| try { |
| provider.flush(); |
| } catch (IOException e) { |
| // use FrameworkLog directly for shutdown messages - RuntimeLog |
| // is empty by this time |
| AuthPlugin.getDefault().frameworkLogError(SecAuthMessages.errorOnSave, FrameworkLogEntry.ERROR, e); |
| } |
| } |
| preferences.clear(); |
| } |
| } |
| |
| static public void clearPasswordCache() { |
| synchronized (preferences) { |
| for (Iterator i = preferences.values().iterator(); i.hasNext();) { |
| SecurePreferencesRoot provider = (SecurePreferencesRoot) i.next(); |
| provider.clearPasswordCache(); |
| } |
| } |
| } |
| |
| // Not exposed as API; mostly intended for testing |
| static public void close(SecurePreferencesRoot root) { |
| if (root == null) |
| return; |
| synchronized (preferences) { |
| for (Iterator i = preferences.values().iterator(); i.hasNext();) { |
| SecurePreferencesRoot provider = (SecurePreferencesRoot) i.next(); |
| if (!root.equals(provider)) |
| continue; |
| i.remove(); |
| break; |
| } |
| } |
| } |
| |
| static private Map processPassword(Map options, String arg) { |
| if (arg == null || arg.length() == 0) |
| return options; |
| File file = new File(arg); |
| if (!file.canRead()) { |
| String msg = NLS.bind(SecAuthMessages.unableToReadPswdFile, arg); |
| AuthPlugin.getDefault().logError(msg, null); |
| return options; |
| } |
| BufferedReader is = null; |
| try { |
| is = new BufferedReader(new FileReader(file)); |
| StringBuffer buffer = new StringBuffer(); |
| for (;;) { // this eliminates new line characters but that's fine |
| String tmp = is.readLine(); |
| if (tmp == null) |
| break; |
| buffer.append(tmp); |
| } |
| if (buffer.length() == 0) |
| return options; |
| if (options == null) |
| options = new HashMap(1); |
| if (!options.containsKey(IProviderHints.DEFAULT_PASSWORD)) |
| options.put(IProviderHints.DEFAULT_PASSWORD, new PBEKeySpec(buffer.toString().toCharArray())); |
| } catch (IOException e) { |
| String msg = NLS.bind(SecAuthMessages.unableToReadPswdFile, arg); |
| AuthPlugin.getDefault().logError(msg, e); |
| } finally { |
| if (is != null) { |
| try { |
| is.close(); |
| } catch (IOException e) { |
| String msg = NLS.bind(SecAuthMessages.unableToReadPswdFile, arg); |
| AuthPlugin.getDefault().logError(msg, e); |
| } |
| } |
| } |
| return options; |
| } |
| |
| } |