blob: e05d3d61d571a13d817ace13e5d2d9dd19cc6713 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.mina.filter.ssl;
import java.security.KeyStore;
import java.security.SecureRandom;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.ManagerFactoryParameters;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSessionContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
/**
* A factory that creates and configures a new {@link SSLContext}.
* <p>
* If no properties are set the returned {@link SSLContext} will
* be equivalent to what the following creates:
* <pre>
* SSLContext c = SSLContext.getInstance( "TLSv1.2" );
* c.init(null, null, null);
* </pre>
* <p>
* Use the properties prefixed with <code>keyManagerFactory</code> to control
* the creation of the {@link KeyManager} to be used.
* <p>
* Use the properties prefixed with <code>trustManagerFactory</code> to control
* the creation of the {@link TrustManagerFactory} to be used.
*
* @author <a href="http://mina.apache.org">Apache MINA Project</a>
*/
public class SslContextFactory {
private String provider = null;
private String protocol = "TLSv1.2";
private SecureRandom secureRandom = null;
private KeyStore keyManagerFactoryKeyStore = null;
private char[] keyManagerFactoryKeyStorePassword = null;
private KeyManagerFactory keyManagerFactory = null;
private String keyManagerFactoryAlgorithm = null;
private String keyManagerFactoryProvider = null;
private boolean keyManagerFactoryAlgorithmUseDefault = true;
private KeyStore trustManagerFactoryKeyStore = null;
private TrustManagerFactory trustManagerFactory = null;
private String trustManagerFactoryAlgorithm = null;
private String trustManagerFactoryProvider = null;
private boolean trustManagerFactoryAlgorithmUseDefault = true;
private ManagerFactoryParameters trustManagerFactoryParameters = null;
private int clientSessionCacheSize = -1;
private int clientSessionTimeout = -1;
private int serverSessionCacheSize = -1;
private int serverSessionTimeout = -1;
/**
* Create a new SSLContext instance,using the {@link KeyManagerFactory} and the
* {@link TrustManagerFactory}.
*
* @return The created instance
* @throws Exception If we weren't able to create the SSLContext insyance
*/
public SSLContext newInstance() throws Exception {
KeyManagerFactory kmf = this.keyManagerFactory;
TrustManagerFactory tmf = this.trustManagerFactory;
if (kmf == null) {
String algorithm = keyManagerFactoryAlgorithm;
if (algorithm == null && keyManagerFactoryAlgorithmUseDefault) {
algorithm = KeyManagerFactory.getDefaultAlgorithm();
}
if (algorithm != null) {
if (keyManagerFactoryProvider == null) {
kmf = KeyManagerFactory.getInstance(algorithm);
} else {
kmf = KeyManagerFactory.getInstance(algorithm, keyManagerFactoryProvider);
}
}
}
if (tmf == null) {
String algorithm = trustManagerFactoryAlgorithm;
if (algorithm == null && trustManagerFactoryAlgorithmUseDefault) {
algorithm = TrustManagerFactory.getDefaultAlgorithm();
}
if (algorithm != null) {
if (trustManagerFactoryProvider == null) {
tmf = TrustManagerFactory.getInstance(algorithm);
} else {
tmf = TrustManagerFactory.getInstance(algorithm, trustManagerFactoryProvider);
}
}
}
KeyManager[] keyManagers = null;
if (kmf != null) {
kmf.init(keyManagerFactoryKeyStore, keyManagerFactoryKeyStorePassword);
keyManagers = kmf.getKeyManagers();
}
TrustManager[] trustManagers = null;
if (tmf != null) {
if (trustManagerFactoryParameters != null) {
tmf.init(trustManagerFactoryParameters);
} else {
tmf.init(trustManagerFactoryKeyStore);
}
trustManagers = tmf.getTrustManagers();
}
SSLContext context;
if (provider == null) {
context = SSLContext.getInstance(protocol);
} else {
context = SSLContext.getInstance(protocol, provider);
}
context.init(keyManagers, trustManagers, secureRandom);
if (clientSessionCacheSize >= 0) {
context.getClientSessionContext().setSessionCacheSize(clientSessionCacheSize);
}
if (clientSessionTimeout >= 0) {
context.getClientSessionContext().setSessionTimeout(clientSessionTimeout);
}
if (serverSessionCacheSize >= 0) {
context.getServerSessionContext().setSessionCacheSize(serverSessionCacheSize);
}
if (serverSessionTimeout >= 0) {
context.getServerSessionContext().setSessionTimeout(serverSessionTimeout);
}
return context;
}
/**
* Sets the provider of the new {@link SSLContext}. The default value is
* <tt>null</tt>, which means the default provider will be used.
*
* @param provider the name of the {@link SSLContext} provider
*/
public void setProvider(String provider) {
this.provider = provider;
}
/**
* Sets the protocol to use when creating the {@link SSLContext}. The
* default is <code>TLS</code>.
*
* @param protocol the name of the protocol.
*/
public void setProtocol(String protocol) {
if (protocol == null) {
throw new IllegalArgumentException("protocol");
}
this.protocol = protocol;
}
/**
* If this is set to <tt>true</tt> while no {@link KeyManagerFactory}
* has been set using {@link #setKeyManagerFactory(KeyManagerFactory)} and
* no algorithm has been set using
* {@link #setKeyManagerFactoryAlgorithm(String)} the default algorithm
* return by {@link KeyManagerFactory#getDefaultAlgorithm()} will be used.
* The default value of this property is <tt>true</tt>.
*
* @param useDefault <tt>true</tt> or <tt>false</tt>.
*/
public void setKeyManagerFactoryAlgorithmUseDefault(boolean useDefault) {
this.keyManagerFactoryAlgorithmUseDefault = useDefault;
}
/**
* If this is set to <tt>true</tt> while no {@link TrustManagerFactory}
* has been set using {@link #setTrustManagerFactory(TrustManagerFactory)} and
* no algorithm has been set using
* {@link #setTrustManagerFactoryAlgorithm(String)} the default algorithm
* return by {@link TrustManagerFactory#getDefaultAlgorithm()} will be used.
* The default value of this property is <tt>true</tt>.
*
* @param useDefault <tt>true</tt> or <tt>false</tt>.
*/
public void setTrustManagerFactoryAlgorithmUseDefault(boolean useDefault) {
this.trustManagerFactoryAlgorithmUseDefault = useDefault;
}
/**
* Sets the {@link KeyManagerFactory} to use. If this is set the properties
* which are used by this factory bean to create a {@link KeyManagerFactory}
* will all be ignored.
*
* @param factory the factory.
*/
public void setKeyManagerFactory(KeyManagerFactory factory) {
this.keyManagerFactory = factory;
}
/**
* Sets the algorithm to use when creating the {@link KeyManagerFactory}
* using {@link KeyManagerFactory#getInstance(java.lang.String)} or
* {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}.
* <p>
* This property will be ignored if a {@link KeyManagerFactory} has been
* set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}.
* <p>
* If this property isn't set while no {@link KeyManagerFactory} has been
* set using {@link #setKeyManagerFactory(KeyManagerFactory)} and
* {@link #setKeyManagerFactoryAlgorithmUseDefault(boolean)} has been set to
* <tt>true</tt> the value returned
* by {@link KeyManagerFactory#getDefaultAlgorithm()} will be used instead.
*
* @param algorithm the algorithm to use.
*/
public void setKeyManagerFactoryAlgorithm(String algorithm) {
this.keyManagerFactoryAlgorithm = algorithm;
}
/**
* Sets the provider to use when creating the {@link KeyManagerFactory}
* using
* {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}.
* <p>
* This property will be ignored if a {@link KeyManagerFactory} has been
* set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}.
* <p>
* If this property isn't set and no {@link KeyManagerFactory} has been set
* using {@link #setKeyManagerFactory(KeyManagerFactory)}
* {@link KeyManagerFactory#getInstance(java.lang.String)} will be used
* to create the {@link KeyManagerFactory}.
*
* @param provider the name of the provider.
*/
public void setKeyManagerFactoryProvider(String provider) {
this.keyManagerFactoryProvider = provider;
}
/**
* Sets the {@link KeyStore} which will be used in the call to
* {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when
* the {@link SSLContext} is created.
*
* @param keyStore the key store.
*/
public void setKeyManagerFactoryKeyStore(KeyStore keyStore) {
this.keyManagerFactoryKeyStore = keyStore;
}
/**
* Sets the password which will be used in the call to
* {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when
* the {@link SSLContext} is created.
*
* @param password the password. Use <code>null</code> to disable password.
*/
public void setKeyManagerFactoryKeyStorePassword(String password) {
if (password != null) {
this.keyManagerFactoryKeyStorePassword = password.toCharArray();
} else {
this.keyManagerFactoryKeyStorePassword = null;
}
}
/**
* Sets the {@link TrustManagerFactory} to use. If this is set the
* properties which are used by this factory bean to create a
* {@link TrustManagerFactory} will all be ignored.
*
* @param factory
* the factory.
*/
public void setTrustManagerFactory(TrustManagerFactory factory) {
this.trustManagerFactory = factory;
}
/**
* Sets the algorithm to use when creating the {@link TrustManagerFactory}
* using {@link TrustManagerFactory#getInstance(java.lang.String)} or
* {@link TrustManagerFactory#getInstance(java.lang.String, java.lang.String)}.
* <p>
* This property will be ignored if a {@link TrustManagerFactory} has been
* set directly using {@link #setTrustManagerFactory(TrustManagerFactory)}.
* <p>
* If this property isn't set while no {@link TrustManagerFactory} has been
* set using {@link #setTrustManagerFactory(TrustManagerFactory)} and
* {@link #setTrustManagerFactoryAlgorithmUseDefault(boolean)} has been set to
* <tt>true</tt> the value returned
* by {@link TrustManagerFactory#getDefaultAlgorithm()} will be used instead.
*
* @param algorithm the algorithm to use.
*/
public void setTrustManagerFactoryAlgorithm(String algorithm) {
this.trustManagerFactoryAlgorithm = algorithm;
}
/**
* Sets the {@link KeyStore} which will be used in the call to
* {@link TrustManagerFactory#init(java.security.KeyStore)} when
* the {@link SSLContext} is created.
* <p>
* This property will be ignored if {@link ManagerFactoryParameters} has been
* set directly using {@link #setTrustManagerFactoryParameters(ManagerFactoryParameters)}.
*
* @param keyStore the key store.
*/
public void setTrustManagerFactoryKeyStore(KeyStore keyStore) {
this.trustManagerFactoryKeyStore = keyStore;
}
/**
* Sets the {@link ManagerFactoryParameters} which will be used in the call to
* {@link TrustManagerFactory#init(javax.net.ssl.ManagerFactoryParameters)} when
* the {@link SSLContext} is created.
*
* @param parameters describing provider-specific trust material.
*/
public void setTrustManagerFactoryParameters(ManagerFactoryParameters parameters) {
this.trustManagerFactoryParameters = parameters;
}
/**
* Sets the provider to use when creating the {@link TrustManagerFactory}
* using
* {@link TrustManagerFactory#getInstance(java.lang.String, java.lang.String)}.
* <p>
* This property will be ignored if a {@link TrustManagerFactory} has been
* set directly using {@link #setTrustManagerFactory(TrustManagerFactory)}.
* <p>
* If this property isn't set and no {@link TrustManagerFactory} has been set
* using {@link #setTrustManagerFactory(TrustManagerFactory)}
* {@link TrustManagerFactory#getInstance(java.lang.String)} will be used
* to create the {@link TrustManagerFactory}.
*
* @param provider the name of the provider.
*/
public void setTrustManagerFactoryProvider(String provider) {
this.trustManagerFactoryProvider = provider;
}
/**
* Sets the {@link SecureRandom} to use when initializing the
* {@link SSLContext}. The JVM's default will be used if this isn't set.
*
* @param secureRandom the {@link SecureRandom} or <code>null</code> if the
* JVM's default should be used.
* @see SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], java.security.SecureRandom)
*/
public void setSecureRandom(SecureRandom secureRandom) {
this.secureRandom = secureRandom;
}
/**
* Sets the SSLSession cache size for the {@link SSLSessionContext} for use in client mode.
*
* @param size the new session cache size limit; zero means there is no limit.
* @see SSLSessionContext#setSessionCacheSize(int size)
*/
public void setClientSessionCacheSize(int size) {
this.clientSessionCacheSize = size;
}
/**
* Set the SSLSession timeout limit for the {@link SSLSessionContext} for use in client mode.
*
* @param seconds the new session timeout limit in seconds; zero means there is no limit.
* @see SSLSessionContext#setSessionTimeout(int seconds)
*/
public void setClientSessionTimeout(int seconds) {
this.clientSessionTimeout = seconds;
}
/**
* Sets the SSLSession cache size for the {@link SSLSessionContext} for use in server mode.
*
* @param serverSessionCacheSize the new session cache size limit; zero means there is no limit.
* @see SSLSessionContext#setSessionCacheSize(int)
*/
public void setServerSessionCacheSize(int serverSessionCacheSize) {
this.serverSessionCacheSize = serverSessionCacheSize;
}
/**
* Set the SSLSession timeout limit for the {@link SSLSessionContext} for use in server mode.
*
* @param serverSessionTimeout the new session timeout limit in seconds; zero means there is no limit.
* @see SSLSessionContext#setSessionTimeout(int)
*/
public void setServerSessionTimeout(int serverSessionTimeout) {
this.serverSessionTimeout = serverSessionTimeout;
}
}