You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by tr...@apache.org on 2014/01/23 23:45:55 UTC
svn commit: r1560840 - in /jackrabbit/commons/filevault/trunk:
vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/
vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/
vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/
Author: tripod
Date: Thu Jan 23 22:45:55 2014
New Revision: 1560840
URL: http://svn.apache.org/r1560840
Log:
JCRVLT-26 File vault stores passwords in clear text in ~/.vault/auth.xml
- adding new option --update-credentials
- adding prompt for password if missing in --credentials
- avoid storing credentials if not explicitely indicated (except admin:admin)
Removed:
jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/DefaultCredentialsProvider.java
Modified:
jackrabbit/commons/filevault/trunk/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/VaultFsApp.java
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/SimpleCredentialsConfig.java
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/VaultAuthConfig.java
jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/ConfigCredentialsProvider.java
Modified: jackrabbit/commons/filevault/trunk/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/VaultFsApp.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/VaultFsApp.java?rev=1560840&r1=1560839&r2=1560840&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/VaultFsApp.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/VaultFsApp.java Thu Jan 23 22:45:55 2014
@@ -58,7 +58,7 @@ import org.apache.jackrabbit.vault.util.
import org.apache.jackrabbit.vault.util.console.util.Log4JConfig;
import org.apache.jackrabbit.vault.util.console.util.PomProperties;
import org.apache.jackrabbit.vault.vlt.ConfigCredentialsProvider;
-import org.apache.jackrabbit.vault.vlt.DefaultCredentialsProvider;
+import org.apache.jackrabbit.vault.vlt.CredentialsProvider;
import org.apache.jackrabbit.vault.vlt.VltContext;
import org.apache.jackrabbit.vault.vlt.VltDirectory;
import org.apache.jackrabbit.vault.vlt.meta.MetaDirectory;
@@ -92,8 +92,7 @@ public class VaultFsApp extends Abstract
private RepositoryProvider repProvider;
- private DefaultCredentialsProvider defCredsProvider;
-
+ private CredentialsProvider credentialsProvider;
private ConfigCredentialsProvider confCredsProvider;
private Repository rep;
@@ -107,6 +106,7 @@ public class VaultFsApp extends Abstract
private Option optCreds;
//private Option optMountpoint;
private Option optConfig;
+ private Option optUpdateCreds;
private ExtendedOption[] xOpts = new ExtendedOption[]{
new XJcrLog(),
@@ -134,10 +134,10 @@ public class VaultFsApp extends Abstract
try {
// hack for setting the default credentials
if (ctxRepository != null) {
- defCredsProvider.setDefaultCredentials(getProperty(KEY_DEFAULT_CREDS));
+ confCredsProvider.setDefaultCredentials(getProperty(KEY_DEFAULT_CREDS));
}
File cwd = getPlatformFile("", true).getCanonicalFile();
- return new VltContext(cwd, localFile, repProvider, confCredsProvider);
+ return new VltContext(cwd, localFile, repProvider, credentialsProvider);
} catch (IOException e) {
throw new ExecutionException(e);
} catch (ConfigurationException e) {
@@ -463,8 +463,8 @@ public class VaultFsApp extends Abstract
// init providers
repProvider = new RepositoryProvider();
- defCredsProvider = new DefaultCredentialsProvider();
- confCredsProvider = new ConfigCredentialsProvider(defCredsProvider);
+ confCredsProvider = new ConfigCredentialsProvider();
+ credentialsProvider = new PasswordPromptingCredentialProvider(confCredsProvider);
// setup default config
setProperty(KEY_DEFAULT_CREDS, null);
@@ -544,12 +544,17 @@ public class VaultFsApp extends Abstract
.withLongName("credentials")
.withDescription("The default credentials to use")
.withArgument(new ArgumentBuilder()
- .withDescription("Format: <user:pass>. If missing an anoymous login is used")
+ .withDescription("Format: <user:pass>. If missing an anonymous login is used. " +
+ "If the password is not specified it is prompted via console.")
.withMinimum(0)
.withMaximum(1)
.create()
)
.create();
+ optUpdateCreds = new DefaultOptionBuilder()
+ .withLongName("update-credentials")
+ .withDescription("if present the credentials-to-host list is updated in the ~/.vault/auth.xml")
+ .create();
/*
optMountpoint = new DefaultOptionBuilder()
.withLongName("mountpoint")
@@ -580,6 +585,7 @@ public class VaultFsApp extends Abstract
//gbuilder.withOption(optURI);
//gbuilder.withOption(optWorkspace);
gbuilder.withOption(optCreds);
+ gbuilder.withOption(optUpdateCreds);
//gbuilder.withOption(optMountpoint);
gbuilder.withOption(optConfig);
return super.addApplicationOptions(gbuilder);
@@ -620,12 +626,43 @@ public class VaultFsApp extends Abstract
if (cl.getValue(optCreds) != null) {
String userPass = (String) cl.getValue(optCreds);
setProperty(KEY_DEFAULT_CREDS, userPass);
- confCredsProvider.setDefaultCredentials(userPass);
+ confCredsProvider.setCredentials(userPass);
+ confCredsProvider.setStoreEnabled(cl.hasOption(optUpdateCreds));
}
if (cl.getValue(optConfig) != null) {
setProperty(KEY_DEFAULT_CONFIG_XML, (String) cl.getValue(optConfig));
}
}
+ private static class PasswordPromptingCredentialProvider implements CredentialsProvider {
+
+ private CredentialsProvider base;
+
+ private PasswordPromptingCredentialProvider(CredentialsProvider base) {
+ this.base = base;
+ }
+
+ public Credentials getCredentials(RepositoryAddress mountpoint) {
+ Credentials creds = base.getCredentials(mountpoint);
+ if (creds instanceof SimpleCredentials) {
+ try {
+ SimpleCredentials simpleCredentials = (SimpleCredentials) creds;
+ if (simpleCredentials.getPassword().length == 0) {
+ System.out.printf("Please enter password for user %s connecting to %s: ",
+ simpleCredentials.getUserID(), mountpoint);
+ String password = new jline.ConsoleReader().readLine('*');
+ creds = new SimpleCredentials(simpleCredentials.getUserID(), password.toCharArray());
+ }
+ } catch (IOException e) {
+ log.error("Error while opening console for reading password" + e);
+ }
+ }
+ return creds;
+ }
+
+ public void storeCredentials(RepositoryAddress mountpoint, Credentials creds) {
+ base.storeCredentials(mountpoint, creds);
+ }
+ }
}
Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/SimpleCredentialsConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/SimpleCredentialsConfig.java?rev=1560840&r1=1560839&r2=1560840&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/SimpleCredentialsConfig.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/SimpleCredentialsConfig.java Thu Jan 23 22:45:55 2014
@@ -17,9 +17,18 @@
package org.apache.jackrabbit.vault.fs.config;
+import java.io.ByteArrayOutputStream;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
import javax.jcr.Credentials;
import javax.jcr.SimpleCredentials;
+import org.apache.jackrabbit.vault.util.Text;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
@@ -33,6 +42,21 @@ import org.xml.sax.helpers.AttributesImp
*/
public class SimpleCredentialsConfig extends CredentialsConfig {
+ /**
+ * key length
+ */
+ private final static int KEY_LENGTH = 8;
+
+ /**
+ * encryption prefix
+ */
+ private final static String PREFIX = "{DES}";
+
+ /**
+ * default logger
+ */
+ private static final Logger log = LoggerFactory.getLogger(SimpleCredentialsConfig.class);
+
private final SimpleCredentials creds;
public static final String ELEM_USER = "user";
public static final String ATTR_NAME = "name";
@@ -57,7 +81,7 @@ public class SimpleCredentialsConfig ext
if (child.getNodeName().equals(ELEM_USER)) {
Element e = (Element) child;
String name = e.getAttribute(ATTR_NAME);
- String pass = e.getAttribute(ATTR_PASSWORD);
+ String pass = decrypt(e.getAttribute(ATTR_PASSWORD));
return new SimpleCredentialsConfig(
new SimpleCredentials(
name,
@@ -72,9 +96,67 @@ public class SimpleCredentialsConfig ext
if (creds != null) {
AttributesImpl attrs = new AttributesImpl();
attrs.addAttribute("", ATTR_NAME, "", "CDATA", creds.getUserID());
- attrs.addAttribute("", ATTR_PASSWORD, "", "CDATA", new String(creds.getPassword()));
+ attrs.addAttribute("", ATTR_PASSWORD, "", "CDATA", encrypt(new String(creds.getPassword())));
handler.startElement("", ELEM_USER, "", attrs);
handler.endElement("", ELEM_USER, "");
}
}
+
+ /**
+ * Encrypts the given string in a fairly secure way so that it can be
+ * {@link #decrypt(String) decrypted} again.
+ *
+ * @param s string to encrypt
+ * @return the encrypted string with a "{AES}" prefix.
+ */
+ private static String encrypt(String s) {
+ try {
+ SecretKey key = KeyGenerator.getInstance("DES").generateKey();
+ Cipher cipher = Cipher.getInstance("DES");
+ byte[] keyBytes = key.getEncoded();
+ byte[] data = s.getBytes("utf-8");
+ ByteArrayOutputStream out = new ByteArrayOutputStream(keyBytes.length + data.length);
+ out.write(keyBytes);
+ cipher.init(Cipher.ENCRYPT_MODE, key);
+ out.write(cipher.update(data));
+ out.write(cipher.doFinal());
+ StringBuilder ret = new StringBuilder(PREFIX);
+ for (byte b: out.toByteArray()) {
+ ret.append(Text.hexTable[b>>4 & 0x0f]).append(Text.hexTable[b&0x0f]);
+ }
+ return ret.toString();
+ } catch (Exception e) {
+ log.warn("Unable to encrypt string: " + e);
+ return null;
+ }
+ }
+
+ /**
+ * Decrypts a string that was previously {@link #encrypt(String)} encrypted}.
+ *
+ * @param s the data to decrypt
+ * @return the string or <code>null</code> if an internal error occurred
+ */
+ private static String decrypt(String s) {
+ if (s == null || !s.startsWith(PREFIX)) {
+ return s;
+ }
+ try {
+ byte[] data = new byte[(s.length() - PREFIX.length())/2];
+ for (int i=PREFIX.length(),b=0; i<s.length(); i+=2, b++) {
+ data[b] = (byte) (Integer.parseInt(s.substring(i, i+2), 16) &0xff);
+ }
+ SecretKeySpec key = new SecretKeySpec(data, 0, KEY_LENGTH, "DES");
+ Cipher cipher = Cipher.getInstance("DES");
+ ByteArrayOutputStream out = new ByteArrayOutputStream(data.length);
+ cipher.init(Cipher.DECRYPT_MODE, key);
+ out.write(cipher.update(data, KEY_LENGTH, data.length - KEY_LENGTH));
+ out.write(cipher.doFinal());
+ return out.toString("utf-8");
+ } catch (Exception e) {
+ log.warn("Unable to decrypt data: " + e);
+ return null;
+ }
+ }
+
}
\ No newline at end of file
Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/VaultAuthConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/VaultAuthConfig.java?rev=1560840&r1=1560839&r2=1560840&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/VaultAuthConfig.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/VaultAuthConfig.java Thu Jan 23 22:45:55 2014
@@ -82,7 +82,11 @@ public class VaultAuthConfig extends Abs
}
public void save() throws IOException {
- save(new File(getConfigDir(), Constants.AUTH_XML));
+ save(getConfigFile());
+ }
+
+ public File getConfigFile() throws IOException {
+ return new File(getConfigDir(), Constants.AUTH_XML);
}
public static class RepositoryConfig {
@@ -116,9 +120,9 @@ public class VaultAuthConfig extends Abs
Node child = nl.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE) {
if (child.getNodeName().equals(CredentialsConfig.ELEM_CREDETIALS)) {
- CredentialsConfig ccfg = CredentialsConfig.load((Element) child);
- if (ccfg != null) {
- cfg.creds = ccfg;
+ CredentialsConfig credentialsConfig = CredentialsConfig.load((Element) child);
+ if (credentialsConfig != null) {
+ cfg.creds = credentialsConfig;
}
} else {
throw new ConfigurationException("unexpected element: " + child.getLocalName());
Modified: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/ConfigCredentialsProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/ConfigCredentialsProvider.java?rev=1560840&r1=1560839&r2=1560840&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/ConfigCredentialsProvider.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/ConfigCredentialsProvider.java Thu Jan 23 22:45:55 2014
@@ -32,14 +32,19 @@ import org.slf4j.LoggerFactory;
* <code>CredentialsProvider</code>...
*
*/
-public class ConfigCredentialsProvider extends DefaultCredentialsProvider {
+public class ConfigCredentialsProvider implements CredentialsProvider {
protected static Logger log = LoggerFactory.getLogger(ConfigCredentialsProvider.class);
private VaultAuthConfig config;
- public ConfigCredentialsProvider(CredentialsProvider base) {
- super(base);
+ private Credentials defaultCreds;
+
+ private Credentials credentials;
+
+ private boolean storeEnabled;
+
+ public ConfigCredentialsProvider() {
config = new VaultAuthConfig();
try {
config.load();
@@ -50,21 +55,38 @@ public class ConfigCredentialsProvider e
}
}
+ public void setDefaultCredentials(String userPass) {
+ this.defaultCreds = fromUserPass(userPass);
+ }
+
+ public void setCredentials(String userPass) {
+ this.credentials = fromUserPass(userPass);
+ }
+
+ private static Credentials fromUserPass(String userPass) {
+ if (userPass != null) {
+ int idx = userPass.indexOf(':');
+ if (idx > 0) {
+ return new SimpleCredentials(userPass.substring(0, idx), userPass.substring(idx + 1).toCharArray());
+ } else {
+ return new SimpleCredentials(userPass, new char[0]);
+ }
+ }
+ return null;
+ }
+
public Credentials getCredentials(RepositoryAddress mountpoint) {
- // check if temporary creds are set
- if (super.getCredentials(mountpoint) != null) {
- return super.getCredentials(mountpoint);
+ if (credentials != null) {
+ return credentials;
}
Credentials creds = fetchCredentials(mountpoint);
return creds == null
- ? super.getCredentials(mountpoint)
+ ? defaultCreds
: creds;
}
private Credentials fetchCredentials(RepositoryAddress mountpoint) {
- VaultAuthConfig.RepositoryConfig cfg = config.getRepoConfig(
- getLookupId(mountpoint)
- );
+ VaultAuthConfig.RepositoryConfig cfg = config.getRepoConfig(getLookupId(mountpoint));
if (cfg == null) {
return null;
}
@@ -82,15 +104,28 @@ public class ConfigCredentialsProvider e
}
return;
}
- VaultAuthConfig.RepositoryConfig cfg = new VaultAuthConfig.RepositoryConfig(
- getLookupId(mountpoint)
- );
- cfg.addCredsConfig(new SimpleCredentialsConfig(((SimpleCredentials) creds)));
- config.addRepositoryConfig(cfg);
- try {
- config.save();
- } catch (IOException e) {
- log.error("Error while saving auth configuration: {} ", e.toString());
+ Credentials currentCreds = fetchCredentials(mountpoint);
+ if (creds.equals(currentCreds)) {
+ // don't update if already stored
+ return;
}
+
+ SimpleCredentials simpleCredentials = (SimpleCredentials) creds;
+ if (storeEnabled ||
+ "admin".equals(simpleCredentials.getUserID()) && "admin".equals(new String(simpleCredentials.getPassword()))) {
+ VaultAuthConfig.RepositoryConfig cfg = new VaultAuthConfig.RepositoryConfig(getLookupId(mountpoint));
+ cfg.addCredsConfig(new SimpleCredentialsConfig(simpleCredentials));
+ config.addRepositoryConfig(cfg);
+ try {
+ config.save();
+ log.warn("Credentials for {} updated in {}.", mountpoint, config.getConfigFile().getPath());
+ } catch (IOException e) {
+ log.error("Error while saving auth configuration: {} ", e.toString());
+ }
+ }
+ }
+
+ public void setStoreEnabled(boolean storeEnabled) {
+ this.storeEnabled = storeEnabled;
}
}
\ No newline at end of file