blob: 70576104c4936ead2a01ede0cd387d3f8538e131 [file] [log] [blame]
/*******************************************************************************
* 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;
}
}