/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.security.plugins;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyStore;
import java.security.Provider;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509KeyManager;
import javax.security.auth.callback.CallbackHandler;
import org.jboss.crypto.CryptoUtil;
import org.jboss.managed.api.ManagedOperation.Impact;
import org.jboss.managed.api.annotation.ManagementComponent;
import org.jboss.managed.api.annotation.ManagementObject;
import org.jboss.managed.api.annotation.ManagementObjectID;
import org.jboss.managed.api.annotation.ManagementOperation;
import org.jboss.managed.api.annotation.ManagementParameter;
import org.jboss.managed.api.annotation.ManagementProperties;
import org.jboss.managed.api.annotation.ManagementProperty;
import org.jboss.managed.api.annotation.ViewUse;
import org.jboss.mx.util.MBeanServerLocator;
import org.jboss.security.ISecurityManagement;
import org.jboss.security.SecurityDomain;
import org.jboss.security.Util;
import org.jboss.security.auth.callback.JBossCallbackHandler;
import org.jboss.security.integration.JNDIBasedSecurityManagement;
import org.jboss.security.integration.SecurityConstantsBridge;
/**
* The JaasSecurityDomain is an extension of JaasSecurityManager that addes the notion of a KeyStore, and JSSE
* KeyManagerFactory and TrustManagerFactory for supporting SSL and other cryptographic use cases.
*
* Attributes:
* <ul>
* <li>KeyStoreType: The implementation type name being used, defaults to 'JKS'. </li>
*
* <li>KeyStoreURL: Set the KeyStore database URL string. This is used to obtain an InputStream to initialize the
* KeyStore. If the string is not a value URL, its treated as a file. </li>
*
* <li>KeyStorePass: the password used to load the KeyStore. Its format is one of:
* <ul>
* <li>The plaintext password for the KeyStore(or whatever format is used by the KeyStore). The toCharArray() value of
* the string is used without any manipulation. </li>
* <li>A command to execute to obtain the plaintext password. The format is '{EXT}...' 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. </li>
* <li>A class to create to obtain the plaintext password. The format is '{CLASS}classname[:ctorarg]' where the
* '[:ctorarg]' is an optional string delimited by the ':' from the classname that will be passed to the classname ctor.
* The password is obtained from classname by invoking a 'char[] toCharArray()' method if found, otherwise, the 'String
* toString()' method is used. </li>
* </ul>
* The KeyStorePass is also used in combination with the Salt and IterationCount attributes to create a PBE secret key
* used with the encode/decode operations. </li>
*
* <li>ManagerServiceName: The JMX object name string of the security manager service that the domain registers with to
* function as a security manager for the security domain name passed to the ctor. The makes the JaasSecurityDomain
* available under the standard JNDI java:/jaas/(domain) binding. </li>
*
* <li>LoadSunJSSEProvider: A flag indicating if the Sun com.sun.net.ssl.internal.ssl.Provider security provider should
* be loaded on startup. This is needed when using the Sun JSSE jars without them installed as an extension with JDK
* 1.3. This should be set to false with JDK 1.4 or when using an alternate JSSE provider </li>
*
* <li>Salt: </li>
*
* <li>IterationCount: </li>
* </ul>
*
* @todo add support for encode/decode based on a SecretKey in the keystore.
*
* @author Scott.Stark@jboss.org
* @author <a href="mailto:jasone@greenrivercomputing.com">Jason Essington</a>
*
* @version $Revision: 106477 $
*/
@ManagementObject(componentType = @ManagementComponent(type = "MCBean", subtype = "Security"), properties = ManagementProperties.EXPLICIT)
public class JaasSecurityDomain extends JaasSecurityManager implements SecurityDomain, JaasSecurityDomainMBean
{
/** The permission required to access encode, encode64 */
private static final RuntimePermission encodePermission = new RuntimePermission(
"org.jboss.security.plugins.JaasSecurityDomain.encode");
/** The permission required to access decode, decode64 */
private static final RuntimePermission decodePermission = new RuntimePermission(
"org.jboss.security.plugins.JaasSecurityDomain.decode");
/** The KeyStore associated with the security domain */
private KeyStore keyStore;
private KeyManagerFactory keyMgr;
/** The KeyStore implementation type which defaults to 'JKS' */
private String keyStoreType = "JKS";
/** The resource for the keystore location */
private URL keyStoreURL;
/** The keystore password for loading */
private char[] keyStorePassword;
/** The alias of the KeyStore to be used */
private String keyStoreAlias;
/** The secret key that corresponds to the keystore password */
private SecretKey cipherKey;
/** The encode/decode cipher algorigthm */
private String cipherAlgorithm = "PBEwithMD5andDES";
private byte[] salt = {1, 2, 3, 4, 5, 6, 7, 8};
private int iterationCount = 103;
private PBEParameterSpec cipherSpec;
/** The JMX object name of the security manager service */
private ObjectName managerServiceName = JaasSecurityManagerServiceMBean.OBJECT_NAME;
private KeyStore trustStore;
private String trustStoreType = "JKS";
private char[] trustStorePassword;
private URL trustStoreURL;
private TrustManagerFactory trustMgr;
private String keyStoreProvider;
private String trustStoreProvider;
private String keyMgrFactoryProvider;
private String trustMgrFactoryProvider;
private String keyMgrFactoryAlgorithm;
private String trustMgrFactoryAlgorithm;
private String keyStoreProviderArgument;
private String trustStoreProviderArgument;
/** Specify the SecurityManagement instance */
private ISecurityManagement securityManagement = SecurityConstantsBridge.getSecurityManagement();
/**
* Creates a default JaasSecurityDomain for with a securityDomain name of 'other'.
*/
public JaasSecurityDomain()
{
super();
}
/**
* Creates a JaasSecurityDomain for with a securityDomain name of that given by the 'securityDomain' argument.
*
* @param securityDomain , the name of the security domain
*/
public JaasSecurityDomain(String securityDomain)
{
this(securityDomain, new JBossCallbackHandler());
}
/**
* Creates a JaasSecurityDomain for with a securityDomain name of that given by the 'securityDomain' argument.
*
* @param securityDomain , the name of the security domain
* @param handler , the CallbackHandler to use to obtain login module info
*/
public JaasSecurityDomain(String securityDomain, CallbackHandler handler)
{
super(securityDomain, handler);
}
@Override
@ManagementObjectID(type = "SecurityDomain")
@ManagementProperty(use = {ViewUse.CONFIGURATION}, description = "The security domain name")
public String getSecurityDomain()
{
return super.getSecurityDomain();
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#getKeyStoreType()
*/
@ManagementProperty(use = {ViewUse.CONFIGURATION}, description = "The keystore implementation type - default is JKS")
public String getKeyStoreType()
{
return this.keyStoreType;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#setKeyStoreType(java.lang.String)
*/
public void setKeyStoreType(String type)
{
this.keyStoreType = type;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#getKeyStoreURL()
*/
@ManagementProperty(use = {ViewUse.CONFIGURATION}, description = "The keystore location")
public String getKeyStoreURL()
{
String url = null;
if (keyStoreURL != null)
url = keyStoreURL.toExternalForm();
return url;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#setKeyStoreURL(java.lang.String)
*/
public void setKeyStoreURL(String storeURL) throws IOException
{
this.keyStoreURL = this.validateStoreURL(storeURL);
log.debug("Using KeyStore=" + keyStoreURL.toExternalForm());
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#setKeyStorePass(java.lang.String)
*/
@ManagementProperty(use = {ViewUse.CONFIGURATION}, description = "The keystore password", mandatory = true)
public void setKeyStorePass(String password) throws Exception
{
this.keyStorePassword = Util.loadPassword(password);
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#getKeyStoreAlias()
*/
@ManagementProperty(use = {ViewUse.CONFIGURATION}, description = "The keystore alias with the certificate to be used")
public String getKeyStoreAlias()
{
return this.keyStoreAlias;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#setKeyStoreAlias(java.lang.String)
*/
public void setKeyStoreAlias(String alias)
{
this.keyStoreAlias = alias;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#getTrustStoreType()
*/
@ManagementProperty(use = {ViewUse.CONFIGURATION}, description = "The truststore implementation type - default is JKS")
public String getTrustStoreType()
{
return this.trustStoreType;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#setTrustStoreType(java.lang.String)
*/
public void setTrustStoreType(String type)
{
this.trustStoreType = type;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#getTrustStoreURL()
*/
@ManagementProperty(use = {ViewUse.CONFIGURATION}, description = "The truststore location")
public String getTrustStoreURL()
{
String url = null;
if (trustStoreURL != null)
url = trustStoreURL.toExternalForm();
return url;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#setTrustStoreURL(java.lang.String)
*/
public void setTrustStoreURL(String storeURL) throws IOException
{
this.trustStoreURL = validateStoreURL(storeURL);
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#setTrustStorePass(java.lang.String)
*/
@ManagementProperty(use = {ViewUse.CONFIGURATION}, description = "The truststore password")
public void setTrustStorePass(String password) throws Exception
{
this.trustStorePassword = Util.loadPassword(password);
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#setSalt(java.lang.String)
*/
@ManagementProperty(use = {ViewUse.CONFIGURATION}, description = "The salt for password-based encryption (PBE)")
public void setSalt(String salt)
{
this.salt = salt.getBytes();
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#setIterationCount(int)
*/
@ManagementProperty(use = {ViewUse.CONFIGURATION}, description = "The iteration count for password-based encryption (PBE)")
public void setIterationCount(int iterationCount)
{
this.iterationCount = iterationCount;
}
/**
* <p>
* Obtains the cypher algorithm used in then encode and decode operations.
* </p>
*
* @return a {@code String} representing the name of the cipher algorithm.
*/
@ManagementProperty(use = {ViewUse.CONFIGURATION}, description = "The cipher algorithm used in the encode/decode operations - default is PBEwithMD5andDES")
public String getCipherAlgorithm()
{
return cipherAlgorithm;
}
/**
* <p>
* Sets the cipher algorithm to be used in the encode and decode operations.
* </p>
*
* @param cipherAlgorithm a {@code String} representing the name of the cipher algorithm.
*/
public void setCipherAlgorithm(String cipherAlgorithm)
{
this.cipherAlgorithm = cipherAlgorithm;
}
/**
* The JMX object name string of the security manager service.
*
* @return The JMX object name string of the security manager service.
*/
@ManagementProperty(use = {ViewUse.CONFIGURATION}, description = "The object name of the security manager service")
public ObjectName getManagerServiceName()
{
return this.managerServiceName;
}
/**
* Set the JMX object name string of the security manager service.
*/
public void setManagerServiceName(ObjectName managerServiceName)
{
this.managerServiceName = managerServiceName;
}
/**
* <p>
* Obtains a reference to the {@code ISecurityManagement} implementation that registered this domain.
* </p>
*
* @return a reference to the {@code ISecurityManagement} bean.
*/
@ManagementProperty(use = {ViewUse.CONFIGURATION}, description = "The security manager service bean where this domain is registered")
public ISecurityManagement getSecurityManagement()
{
return securityManagement;
}
/**
* <p>
* Sets the {@code ISecurityManagement} implementation that must be used to register this domain.
* </p>
*
* @param securityManagement a reference to the {@code ISecurityManagement} be to be used.
*/
public void setSecurityManagement(ISecurityManagement securityManagement)
{
this.securityManagement = securityManagement;
}
/*
* (non-Javadoc)
*
* @see org.jboss.system.ServiceMBeanSupport#getName()
*/
@Override
public String getName()
{
return "JaasSecurityDomain(" + getSecurityDomain() + ")";
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.SecurityDomain#getKeyStore()
*/
@ManagementOperation(description = "Get the KeyStore constructed by this domain", impact = Impact.ReadOnly)
public KeyStore getKeyStore() throws SecurityException
{
return keyStore;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.SecurityDomain#getKeyManagerFactory()
*/
@ManagementOperation(description = "Get the KeyManagerFactory constructed by this domain", impact = Impact.ReadOnly)
public KeyManagerFactory getKeyManagerFactory() throws SecurityException
{
return keyMgr;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.SecurityDomain#getTrustStore()
*/
@ManagementOperation(description = "Get the TrustStore constructed by this domain", impact = Impact.ReadOnly)
public KeyStore getTrustStore() throws SecurityException
{
return trustStore;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.SecurityDomain#getTrustManagerFactory()
*/
@ManagementOperation(description = "Get the TrustManagerFactory constructed by this domain", impact = Impact.ReadOnly)
public TrustManagerFactory getTrustManagerFactory() throws SecurityException
{
return trustMgr;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#encode(byte[])
*/
@ManagementOperation(description = "Encode a secret using the cipher algorithm and the KeyStore password",
params = {@ManagementParameter(name = "secret", description = "The secret to be encoded")},
impact = Impact.ReadOnly)
public byte[] encode(byte[] secret) throws Exception
{
SecurityManager sm = System.getSecurityManager();
if (sm != null)
{
if(log.isTraceEnabled())
log.trace("Checking: " + encodePermission);
sm.checkPermission(encodePermission);
}
Cipher cipher = Cipher.getInstance(cipherAlgorithm);
cipher.init(Cipher.ENCRYPT_MODE, cipherKey, cipherSpec);
byte[] encoding = cipher.doFinal(secret);
return encoding;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#decode(byte[])
*/
@ManagementOperation(description = "Decode a secret using the cipher algorithm and the KeyStore password",
params = {@ManagementParameter(name = "secret", description = "The secret to be encoded")},
impact = Impact.ReadOnly)
public byte[] decode(byte[] secret) throws Exception
{
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkPermission(decodePermission);
Cipher cipher = Cipher.getInstance(cipherAlgorithm);
cipher.init(Cipher.DECRYPT_MODE, cipherKey, cipherSpec);
byte[] decode = cipher.doFinal(secret);
return decode;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#encode64(byte[])
*/
@ManagementOperation(description = "Encode a secret as a base64 string using the cipher algorithm and the KeyStore password",
params = {@ManagementParameter(name = "secret", description = "The secret to be encoded")},
impact = Impact.ReadOnly)
public String encode64(byte[] secret) throws Exception
{
byte[] encoding = encode(secret);
String b64 = CryptoUtil.tob64(encoding);
return b64;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#decode64(java.lang.String)
*/
@ManagementOperation(description = "Decode a base64 secret using the cipher algorithm and the KeyStore password",
params = {@ManagementParameter(name = "secret", description = "The secret to be encoded")},
impact = Impact.ReadOnly)
public byte[] decode64(String secret) throws Exception
{
byte[] encoding = CryptoUtil.fromb64(secret);
//JBAS-7094: fix leading zeros
if (encoding.length % 8 != 0)
{
int length = encoding.length;
int newLength = ((length / 8) + 1) * 8;
int pad = newLength - length; //number of leading zeros
byte[] old = encoding;
encoding = new byte[newLength];
for (int i = old.length - 1; i >= 0; i--)
{
encoding[i + pad] = old[i];
}
}
byte[] decode = decode(encoding);
return decode;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#getKeyManagerFactoryProvider
*/
@ManagementProperty(use = {ViewUse.CONFIGURATION}, description = "The security provider of the KeyManagerFactory")
public String getKeyManagerFactoryProvider()
{
return keyMgrFactoryProvider;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#setKeyManagerFactoryProvider(java.lang.String)
*/
public void setKeyManagerFactoryProvider(String provider)
{
this.keyMgrFactoryProvider = provider;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#getKeyStoreProvider
*/
@ManagementProperty(use = {ViewUse.CONFIGURATION}, description = "The security provider of the KeyStore")
public String getKeyStoreProvider()
{
return keyStoreProvider;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#setKeyStoreProvider(java.lang.String)
*/
public void setKeyStoreProvider(String provider)
{
this.keyStoreProvider = provider;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#getTrustManagerFactoryProvider
*/
@ManagementProperty(use = {ViewUse.CONFIGURATION}, description = "The security provider of the TrustManagerFactory")
public String getTrustManagerFactoryProvider()
{
return trustMgrFactoryProvider;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#setTrustManagerFactoryProvider(java.lang.String)
*/
public void setTrustManagerFactoryProvider(String provider)
{
this.trustMgrFactoryProvider = provider;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#getTrustStoreProvider
*/
@ManagementProperty(use = {ViewUse.CONFIGURATION}, description = "The security provider of the TrustStore")
public String getTrustStoreProvider()
{
return trustStoreProvider;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#setTrustStoreProvider(java.lang.String)
*/
public void setTrustStoreProvider(String provider)
{
this.trustStoreProvider = provider;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#getKeyManagerFactoryAlgorithm
*/
@ManagementProperty(use = {ViewUse.CONFIGURATION}, description = "The algorithm of the KeyManagerFactory")
public String getKeyManagerFactoryAlgorithm()
{
return keyMgrFactoryAlgorithm;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#setKeyManagerFactoryAlgorithm(java.lang.String)
*/
public void setKeyManagerFactoryAlgorithm(String algorithm)
{
this.keyMgrFactoryAlgorithm = algorithm;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#getTrustManagerFactoryAlgorithm
*/
@ManagementProperty(use = {ViewUse.CONFIGURATION}, description = "The algorithm of the TrustManagerFactory")
public String getTrustManagerFactoryAlgorithm()
{
return trustMgrFactoryAlgorithm;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#setTrustManagerFactoryAlgorithm(java.lang.String)
*/
public void setTrustManagerFactoryAlgorithm(String algorithm)
{
this.trustMgrFactoryAlgorithm = algorithm;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#getKeyStoreProviderArgument
*/
@ManagementProperty(use = {ViewUse.CONFIGURATION}, description = "The argument of the KeyStore provider constructor")
public String getKeyStoreProviderArgument()
{
return keyStoreProviderArgument;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#setKeyStoreProviderArgument(java.lang.String)
*/
public void setKeyStoreProviderArgument(String argument)
{
this.keyStoreProviderArgument = argument;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#getTrustStoreProviderArgument
*/
@ManagementProperty(use = {ViewUse.CONFIGURATION}, description = "The argument of the TrustStore provider constructor")
public String getTrustStoreProviderArgument()
{
return trustStoreProviderArgument;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#setTrustStoreProviderArgument(java.lang.String)
*/
public void setTrustStoreProviderArgument(String argument)
{
this.trustStoreProviderArgument = argument;
}
/*
* (non-Javadoc)
*
* @see org.jboss.security.plugins.JaasSecurityDomainMBean#reloadKeyAndTrustStore()
*/
@ManagementOperation(description = "Reload the key and trust stores", impact = Impact.WriteOnly)
public void reloadKeyAndTrustStore() throws Exception
{
loadKeyAndTrustStore();
}
/*
* (non-Javadoc)
*
* @see org.jboss.system.ServiceMBeanSupport#startService()
*/
@Override
@ManagementOperation(description = "Service lifecycle operation", impact = Impact.WriteOnly)
protected void startService() throws Exception
{
// Load the secret key
loadPBESecretKey();
// Load the key and/or truststore into memory
loadKeyAndTrustStore();
// Only register with the JaasSecurityManagerService if its defined
if (managerServiceName != null)
{
/*
* Register with the JaasSecurityManagerServiceMBean. This allows this JaasSecurityDomain to function as the
* security manager for security-domain elements that declare java:/jaas/xxx for our security domain name.
*/
MBeanServer server = MBeanServerLocator.locateJBoss();
Object[] params = {getSecurityDomain(), this};
String[] signature = new String[]{"java.lang.String", "org.jboss.security.SecurityDomain"};
server.invoke(managerServiceName, "registerSecurityDomain", params, signature);
}
// Register yourself with the security management
if (securityManagement instanceof JNDIBasedSecurityManagement)
{
JNDIBasedSecurityManagement jbs = (JNDIBasedSecurityManagement) securityManagement;
jbs.registerJaasSecurityDomainInstance(this);
}
}
/*
* (non-Javadoc)
*
* @see org.jboss.system.ServiceMBeanSupport#stopService()
*/
@Override
@ManagementOperation(description = "Service lifecycle operation", impact = Impact.WriteOnly)
protected void stopService()
{
if (keyStorePassword != null)
{
Arrays.fill(keyStorePassword, '\0');
keyStorePassword = null;
}
cipherKey = null;
// Deregister yourself with the security management
if (securityManagement instanceof JNDIBasedSecurityManagement)
{
JNDIBasedSecurityManagement jbs = (JNDIBasedSecurityManagement) securityManagement;
jbs.deregisterJaasSecurityDomainInstance(getSecurityDomain());
}
}
/**
* <p>
* Loads the PBE secret key.
* </p>
*
* @throws Exception if an error ocurrs when loading the PBE key.
*/
private void loadPBESecretKey() throws Exception
{
// Create the PBE secret key
cipherSpec = new PBEParameterSpec(salt, iterationCount);
PBEKeySpec keySpec = new PBEKeySpec(keyStorePassword);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEwithMD5andDES");
cipherKey = factory.generateSecret(keySpec);
}
private void loadKeyAndTrustStore() throws Exception
{
if (keyStorePassword != null)
{
if (keyStoreProvider != null)
{
if (keyStoreProviderArgument != null)
{
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class clazz = loader.loadClass(keyStoreProvider);
Class[] ctorSig = {String.class};
Constructor ctor = clazz.getConstructor(ctorSig);
Object[] ctorArgs = {keyStoreProviderArgument};
Provider provider = (Provider) ctor.newInstance(ctorArgs);
keyStore = KeyStore.getInstance(keyStoreType, provider);
}
else
keyStore = KeyStore.getInstance(keyStoreType, keyStoreProvider);
}
else
keyStore = KeyStore.getInstance(keyStoreType);
InputStream is = null;
if ((!"PKCS11".equalsIgnoreCase(keyStoreType) || !"PKCS11IMPLKS".equalsIgnoreCase(keyStoreType)) && keyStoreURL != null)
{
is = keyStoreURL.openStream();
}
keyStore.load(is, keyStorePassword);
if (keyStoreAlias != null && !keyStore.isKeyEntry(keyStoreAlias))
{
throw new IOException("Cannot find key entry with alias " + keyStoreAlias + " in the keyStore");
}
String algorithm = null;
if (keyMgrFactoryAlgorithm != null)
algorithm = keyMgrFactoryAlgorithm;
else
algorithm = KeyManagerFactory.getDefaultAlgorithm();
if (keyMgrFactoryProvider != null)
keyMgr = KeyManagerFactory.getInstance(algorithm, keyMgrFactoryProvider);
else
keyMgr = KeyManagerFactory.getInstance(algorithm);
keyMgr.init(keyStore, keyStorePassword);
if (keyStoreAlias != null)
{
KeyManager[] keyManagers = keyMgr.getKeyManagers();
for (int i = 0; i < keyManagers.length; i++)
{
keyManagers[i] = new SecurityKeyManager((X509KeyManager) keyManagers[i], keyStoreAlias);
}
}
}
if (trustStorePassword != null)
{
if (trustStoreProvider != null)
{
if (trustStoreProviderArgument != null)
{
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class clazz = loader.loadClass(trustStoreProvider);
Class[] ctorSig = {String.class};
Constructor ctor = clazz.getConstructor(ctorSig);
Object[] ctorArgs = {trustStoreProviderArgument};
Provider provider = (Provider) ctor.newInstance(ctorArgs);
trustStore = KeyStore.getInstance(trustStoreType, provider);
}
else
trustStore = KeyStore.getInstance(trustStoreType, trustStoreProvider);
}
else
trustStore = KeyStore.getInstance(trustStoreType);
InputStream is = null;
if ((!"PKCS11".equalsIgnoreCase(trustStoreType) || !"PKCS11IMPLKS".equalsIgnoreCase(trustStoreType)) && trustStoreURL != null)
{
is = trustStoreURL.openStream();
}
trustStore.load(is, trustStorePassword);
String algorithm = null;
if (trustMgrFactoryAlgorithm != null)
algorithm = trustMgrFactoryAlgorithm;
else
algorithm = TrustManagerFactory.getDefaultAlgorithm();
if (trustMgrFactoryProvider != null)
trustMgr = TrustManagerFactory.getInstance(algorithm, trustStoreProvider);
else
trustMgr = TrustManagerFactory.getInstance(algorithm);
trustMgr.init(trustStore);
}
else if (keyStore != null)
{
trustStore = keyStore;
String algorithm = null;
if (trustMgrFactoryAlgorithm != null)
algorithm = trustMgrFactoryAlgorithm;
else
algorithm = TrustManagerFactory.getDefaultAlgorithm();
trustMgr = TrustManagerFactory.getInstance(algorithm);
trustMgr.init(trustStore);
}
}
private URL validateStoreURL(String storeURL) throws IOException
{
URL url = null;
// First see if this is a URL
try
{
url = new URL(storeURL);
}
catch (MalformedURLException e)
{
// Not a URL or a protocol without a handler
}
// Next try to locate this as file path
if (url == null)
{
File tst = new File(storeURL);
if (tst.exists() == true)
url = tst.toURL();
}
// Last try to locate this as a classpath resource
if (url == null)
{
ClassLoader loader = SubjectActions.getContextClassLoader();
url = loader.getResource(storeURL);
}
// Fail if no valid key store was located
if (url == null)
{
String msg = "Failed to find url=" + storeURL + " as a URL, file or resource";
throw new MalformedURLException(msg);
}
return url;
}
}