[jboss-cvs] Picketbox SVN: r485 - in trunk: security-jboss-sx/jbosssx/src/main/java/org/picketbox/plugins/vault and 5 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Tue Dec 3 06:37:46 EST 2013
Author: pskopek at redhat.com
Date: 2013-12-03 06:37:46 -0500 (Tue, 03 Dec 2013)
New Revision: 485
Added:
trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/security/vault/KeystorePasswordProvider.java
trunk/security-jboss-sx/jbosssx/src/test/resources/bin/
trunk/security-jboss-sx/jbosssx/src/test/resources/bin/askpass.sh
Modified:
trunk/picketbox-infinispan/.settings/org.eclipse.jdt.core.prefs
trunk/security-jboss-sx/jbosssx/src/main/java/org/picketbox/plugins/vault/PicketBoxSecurityVault.java
trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/SecurityActions.java
trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/security/vault/SecurityVaultUnitTestCase.java
trunk/security-spi/common/src/main/java/org/jboss/security/PicketBoxMessages.java
Log:
[SECURITY-770] Support external password for keystore of PicketBoxVault implementation
patch by Ivo
Modified: trunk/picketbox-infinispan/.settings/org.eclipse.jdt.core.prefs
===================================================================
--- trunk/picketbox-infinispan/.settings/org.eclipse.jdt.core.prefs 2013-11-06 02:16:30 UTC (rev 484)
+++ trunk/picketbox-infinispan/.settings/org.eclipse.jdt.core.prefs 2013-12-03 11:37:46 UTC (rev 485)
@@ -1,12 +1,12 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.5
Modified: trunk/security-jboss-sx/jbosssx/src/main/java/org/picketbox/plugins/vault/PicketBoxSecurityVault.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/main/java/org/picketbox/plugins/vault/PicketBoxSecurityVault.java 2013-11-06 02:16:30 UTC (rev 484)
+++ trunk/security-jboss-sx/jbosssx/src/main/java/org/picketbox/plugins/vault/PicketBoxSecurityVault.java 2013-12-03 11:37:46 UTC (rev 485)
@@ -23,6 +23,7 @@
import org.jboss.security.PicketBoxLogger;
import org.jboss.security.PicketBoxMessages;
+import org.jboss.security.Util;
import org.jboss.security.plugins.PBEUtils;
import org.jboss.security.vault.SecurityVault;
import org.jboss.security.vault.SecurityVaultException;
@@ -62,7 +63,20 @@
* The following options are expected in the {@link SecurityVault#init(Map)} call:
* ENC_FILE_DIR: the location where the encoded files will be kept. End with "/" or "\" based on your platform
* KEYSTORE_URL: location where your keystore is located
- * KEYSTORE_PASSWORD: Masked keystore password. Has to be prepended with MASK-
+ * KEYSTORE_PASSWORD: keystore password.
+ * 'plain text' masked password (has to be prepended with MASK-)
+ * '{EXT}...' where the '...' is the exact command
+ * '{EXTC[:expiration_in_millis]}...' where the '...' is the exact command
+ * line that will be passed to the Runtime.exec(String) method to execute a
+ * platform command. The first line of the command output is used as the
+ * password.
+ * EXTC variant will cache the passwords for expiration_in_millis milliseconds.
+ * Default cache expiration is 0 = infinity.
+ * '{CLASS}classname[:ctorargs]' where the '[:ctorargs]' is an optional
+ * string delimited by the ':' from the classname that will be passed to the
+ * classname ctor. The ctorargs itself is a comma delimited list of strings.
+ * The password is obtained from classname by invoking a
+ * 'char[] toCharArray()' method if found, otherwise, the 'String toString()'
* KEYSTORE_ALIAS: Alias where the keypair is located
* SALT: salt of the masked password. Ensured it is 8 characters in length
* ITERATION_COUNT: Iteration Count of the masked password.
@@ -113,6 +127,10 @@
public static final String PASS_MASK_PREFIX = "MASK-";
+ public static final String PASS_CLASS_PREFIX = "{CLASS}";
+
+ public static final String PASS_EXT_PREFIX = "{EXT";
+
public static final String PUBLIC_CERT = "PUBLIC_CERT";
public static final String KEY_SIZE = "KEY_SIZE";
@@ -147,11 +165,13 @@
}
keystoreURL = StringUtil.getSystemPropertyAsString(keystoreURL);
- String maskedPassword = (String) options.get(KEYSTORE_PASSWORD);
- if(maskedPassword == null)
+ String password = (String) options.get(KEYSTORE_PASSWORD);
+ if(password == null)
throw new SecurityVaultException(PicketBoxMessages.MESSAGES.invalidNullOrEmptyOptionMessage(KEYSTORE_PASSWORD));
- if(maskedPassword.startsWith(PASS_MASK_PREFIX) == false)
- throw new SecurityVaultException(PicketBoxMessages.MESSAGES.invalidUnmaskedKeystorePasswordMessage());
+ if(password.startsWith(PASS_MASK_PREFIX) == false
+ && password.startsWith(PASS_EXT_PREFIX) == false
+ && password.startsWith(PASS_CLASS_PREFIX) == false)
+ throw new SecurityVaultException(PicketBoxMessages.MESSAGES.invalidKeystorePasswordFormatMessage());
String salt = (String) options.get(SALT);
if(salt == null)
@@ -182,8 +202,7 @@
keyStoreType = (options.get(KEYSTORE_TYPE) != null ? (String) options.get(KEYSTORE_TYPE) : defaultKeyStoreType);
try {
- String keystorePass = decode(maskedPassword, salt, iterationCount);
- keyStorePWD = keystorePass.toCharArray();
+ keyStorePWD = loadKeystorePassword(password, salt, iterationCount);
keystore = getKeyStore(keystoreURL);
checkAndConvertKeyStoreToJCEKS(keystoreURL);
@@ -301,7 +320,21 @@
}
return true;
}
-
+
+ private char[] loadKeystorePassword(String passwordDef, String salt, int iterationCount) throws Exception
+ {
+ final char[] password;
+
+ if( passwordDef.startsWith(PASS_MASK_PREFIX) ){
+ String keystorePass = decode(passwordDef, salt, iterationCount);
+ password = keystorePass.toCharArray();
+ }
+ else
+ password = Util.loadPassword(passwordDef);
+
+ return password;
+ }
+
private String decode(String maskedString, String salt, int iterationCount) throws Exception
{
String pbeAlgo = "PBEwithMD5andDES";
Modified: trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/SecurityActions.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/SecurityActions.java 2013-11-06 02:16:30 UTC (rev 484)
+++ trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/SecurityActions.java 2013-12-03 11:37:46 UTC (rev 485)
@@ -74,4 +74,49 @@
}
});
}
+
+ interface SystemPropertyAction
+ {
+ SystemPropertyAction PRIVILEGED = new SystemPropertyAction()
+ {
+ public String getProperty(final String name, final String defaultValue)
+ {
+ String prop = AccessController.doPrivileged(
+ new PrivilegedAction<String>()
+ {
+ public String run()
+ {
+ return NON_PRIVILEGED.getProperty(name, defaultValue);
+ }
+ }
+ );
+ return prop;
+ }
+ };
+ SystemPropertyAction NON_PRIVILEGED = new SystemPropertyAction()
+ {
+ public String getProperty(final String name, final String defaultValue)
+ {
+ final String prop = System.getProperty(name, defaultValue);
+ return prop;
+ }
+ };
+ String getProperty(final String name, final String defaultValue);
+ }
+
+ public static String getProperty(final String name, final String defaultValue)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ final String prop;
+ if( sm != null )
+ {
+ prop = SystemPropertyAction.PRIVILEGED.getProperty(name, defaultValue);
+ }
+ else
+ {
+ prop = SystemPropertyAction.NON_PRIVILEGED.getProperty(name, defaultValue);
+ }
+ return prop;
+ }
+
}
Added: trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/security/vault/KeystorePasswordProvider.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/security/vault/KeystorePasswordProvider.java (rev 0)
+++ trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/security/vault/KeystorePasswordProvider.java 2013-12-03 11:37:46 UTC (rev 485)
@@ -0,0 +1,14 @@
+package org.jboss.test.security.vault;
+
+/**
+ * Testing password provider for a Vault keystore.
+ *
+ * @author <a href="mailto:istudens at redhat.com">Ivo Studensky</a>
+ */
+public class KeystorePasswordProvider
+{
+ public char[] toCharArray()
+ {
+ return "vault22".toCharArray();
+ }
+}
Modified: trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/security/vault/SecurityVaultUnitTestCase.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/security/vault/SecurityVaultUnitTestCase.java 2013-11-06 02:16:30 UTC (rev 484)
+++ trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/security/vault/SecurityVaultUnitTestCase.java 2013-12-03 11:37:46 UTC (rev 485)
@@ -26,6 +26,8 @@
import org.jboss.security.vault.SecurityVaultException;
import org.jboss.security.vault.SecurityVaultFactory;
import org.jboss.security.vault.SecurityVaultUtil;
+import org.jboss.test.SecurityActions;
+import org.junit.Assume;
import org.junit.Test;
import org.picketbox.plugins.vault.PicketBoxSecurityVault;
@@ -43,8 +45,6 @@
import java.util.HashMap;
import java.util.Map;
-import junit.framework.Assert;
-
import static org.junit.Assert.*;
/**
@@ -164,7 +164,97 @@
assertFalse(vault.exists(vaultBlock+"1", attributeName+"2"));
}
-
+ @Test
+ public void testClassBasedKeystorePassword() throws Exception
+ {
+
+ setInitialVaulConditions("src/test/resources/keystore/vault.jks", "target/vaults/vault2/vault.jks",
+ "src/test/resources/keystore/vault_data", "target/vaults/vault2/vault_data");
+
+ Map<String,Object> options = getVaultOptionsMap(
+ "target/vaults/vault2/vault.jks",
+ "target/vaults/vault2/vault_data",
+ "vault", "12438567", 50, "{CLASS}org.jboss.test.security.vault.KeystorePasswordProvider");
+
+ String vaultBlock = "aBlock";
+ String attributeName = "anAttribute";
+
+ char[] attributeValue = "aValue".toCharArray();
+
+ SecurityVault vault = getNewSecurityVaultInstance();
+
+ vault.init(options);
+ assertTrue(vault.isInitialized());
+
+ Map<String,Object> handshakeOptions = new HashMap<String,Object>();
+
+ byte[] sharedKey = vault.handshake(handshakeOptions);
+ assertNotNull(sharedKey);
+
+ vault.store(vaultBlock, attributeName, attributeValue , sharedKey);
+
+ assertTrue(vault.exists(vaultBlock, attributeName));
+ //Now retrieve
+ assertEquals(new String(attributeValue), new String(vault.retrieve(vaultBlock, attributeName, sharedKey)));
+
+ vault.store(vaultBlock+"1", attributeName+"2", attributeValue, sharedKey);
+ assertEquals(new String(attributeValue), new String(vault.retrieve(vaultBlock+"1", attributeName+"2", sharedKey)));
+
+ System.out.println("Currently storing:" + vault.keyList());
+
+ assertTrue(vault.remove(vaultBlock+"1", attributeName+"2", sharedKey));
+ assertFalse(vault.exists(vaultBlock+"1", attributeName+"2"));
+ }
+
+ @Test
+ public void testExtCmdBasedKeystorePassword() throws Exception
+ {
+ // since this test uses an external BASH script it is valid for Linux systems only
+ String OS_NAME = SecurityActions.getProperty("os.name", null);
+ Assume.assumeTrue(OS_NAME.startsWith("Linux") || OS_NAME.startsWith("LINUX"));
+
+ setInitialVaulConditions("src/test/resources/keystore/vault.jks", "target/vaults/vault2/vault.jks",
+ "src/test/resources/keystore/vault_data", "target/vaults/vault2/vault_data");
+
+ String absolutePathToAskPass = SecurityVaultUnitTestCase.class.getResource("/bin/askpass.sh").getFile();
+ System.out.println("absolutePathToAskPass: " + absolutePathToAskPass);
+
+ // 'Enter passphrase for *' is hard-coded into kwalletaskpass for example
+ Map<String,Object> options = getVaultOptionsMap(
+ "target/vaults/vault2/vault.jks",
+ "target/vaults/vault2/vault_data",
+ "vault", "12438567", 50, "{EXT}/bin/sh " + absolutePathToAskPass + " Enter passphrase for askpass test");
+
+ String vaultBlock = "aBlock";
+ String attributeName = "anAttribute";
+
+ char[] attributeValue = "aValue".toCharArray();
+
+ SecurityVault vault = getNewSecurityVaultInstance();
+
+ vault.init(options);
+ assertTrue(vault.isInitialized());
+
+ Map<String,Object> handshakeOptions = new HashMap<String,Object>();
+
+ byte[] sharedKey = vault.handshake(handshakeOptions);
+ assertNotNull(sharedKey);
+
+ vault.store(vaultBlock, attributeName, attributeValue , sharedKey);
+
+ assertTrue(vault.exists(vaultBlock, attributeName));
+ //Now retrieve
+ assertEquals(new String(attributeValue), new String(vault.retrieve(vaultBlock, attributeName, sharedKey)));
+
+ vault.store(vaultBlock+"1", attributeName+"2", attributeValue, sharedKey);
+ assertEquals(new String(attributeValue), new String(vault.retrieve(vaultBlock+"1", attributeName+"2", sharedKey)));
+
+ System.out.println("Currently storing:" + vault.keyList());
+
+ assertTrue(vault.remove(vaultBlock+"1", attributeName+"2", sharedKey));
+ assertFalse(vault.exists(vaultBlock+"1", attributeName+"2"));
+ }
+
/**
* See src/test/resources/vault-v0/readme.txt for initial vault setup (including secured attributes).
* @throws Exception
@@ -345,6 +435,10 @@
private String getMaskedPassword(String pwd, String salt, int iterationCount) throws Exception
{
+ if (pwd.startsWith(PicketBoxSecurityVault.PASS_EXT_PREFIX)
+ || pwd.startsWith(PicketBoxSecurityVault.PASS_CLASS_PREFIX))
+ return pwd;
+
String algo = "PBEwithMD5andDES";
// Create the PBE secret key
@@ -357,7 +451,7 @@
String maskedPass = PBEUtils.encode64(pwd.getBytes(), algo, cipherKey, cipherSpec);
- return new String(PicketBoxSecurityVault.PASS_MASK_PREFIX) + maskedPass;
+ return PicketBoxSecurityVault.PASS_MASK_PREFIX + maskedPass;
}
Added: trunk/security-jboss-sx/jbosssx/src/test/resources/bin/askpass.sh
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/test/resources/bin/askpass.sh (rev 0)
+++ trunk/security-jboss-sx/jbosssx/src/test/resources/bin/askpass.sh 2013-12-03 11:37:46 UTC (rev 485)
@@ -0,0 +1,2 @@
+#!/bin/sh
+echo vault22
\ No newline at end of file
Modified: trunk/security-spi/common/src/main/java/org/jboss/security/PicketBoxMessages.java
===================================================================
--- trunk/security-spi/common/src/main/java/org/jboss/security/PicketBoxMessages.java 2013-11-06 02:16:30 UTC (rev 484)
+++ trunk/security-spi/common/src/main/java/org/jboss/security/PicketBoxMessages.java 2013-12-03 11:37:46 UTC (rev 485)
@@ -456,4 +456,7 @@
@Message(id = 140, value = "Unable to get keystore (%s)")
RuntimeException unableToGetKeyStore(@Cause Throwable throwable, String file);
+
+ @Message(id = 141, value = "Keystore password should be either masked or prefixed with {EXT} or {CLASS}")
+ String invalidKeystorePasswordFormatMessage();
}
\ No newline at end of file
More information about the jboss-cvs-commits
mailing list