/*******************************************************************************
* Copyright 2014 Federal Chancellery Austria
* MOA-ID has been developed in a cooperation between BRZ, the Federal
* Chancellery Austria - ICT staff unit, and Graz University of Technology.
*
* Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
* the European Commission - subsequent versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
* http://www.osor.eu/eupl/
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Licence is distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*
* This product combines work with different licenses. See the "NOTICE" text
* file for details on the various modules and licenses.
* The "NOTICE" text file is part of the distribution. Any derivative works
* that you distribute must include a readable copy of the "NOTICE" text file.
******************************************************************************/
/*
* Copyright 2003 Federal Chancellery Austria
* MOA-ID has been developed in a cooperation between BRZ, the Federal
* Chancellery Austria - ICT staff unit, and Graz University of Technology.
*
* Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
* the European Commission - subsequent versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
* http://www.osor.eu/eupl/
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Licence is distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*
* This product combines work with different licenses. See the "NOTICE" text
* file for details on the various modules and licenses.
* The "NOTICE" text file is part of the distribution. Any derivative works
* that you distribute must include a readable copy of the "NOTICE" text file.
*/
package at.gv.egovernment.moa.id.commons.utils.ssl;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.Security;
import java.util.HashMap;
import java.util.Map;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.KeyStoreUtils;
import iaik.pki.PKIConfiguration;
import iaik.pki.PKIException;
import iaik.pki.PKIFactory;
import iaik.pki.PKIProfile;
import iaik.pki.jsse.IAIKX509TrustManager;
//import iaik.pki.jsse.IAIKX509TrustManager;
import iaik.security.provider.IAIK;
/**
* Utility for a obtaining a secure socket factory using IAIKX509TrustManager
.
* This TrustManager
implementation features CRL checking.
* SSLUtils
caches secure socket factories for given ConnectionParameter
s.
*
* @author Paul Ivancsics
* @version $Id$
*/
public class SSLUtils {
/** SSLSocketFactory store, mapping URL->SSLSocketFactory **/
private static Map sslSocketFactories = new HashMap();
/**
* Initializes the SSLSocketFactory store.
*/
public static void initialize() {
sslSocketFactories = new HashMap();
// JSSE Abhängigkeit
//Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
Security.addProvider(new IAIK());
//System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
}
/**
* Creates an SSLSocketFactory
which utilizes an
* IAIKX509TrustManager
for the given trust store,
* and the given key store.
*
* @param conf configuration provider providing a generic properties pointing
* to trusted CA store and certificate store root
* @param connParam connection parameter containing the client key store settings
* to be used in case of client authentication;
* if connParam.getClientKeyStore() == null
, client authentication
* is assumed to be disabled
* @return SSLSocketFactory
to be used by an HttpsURLConnection
* @throws IOException thrown while reading key store file
* @throws GeneralSecurityException thrown while creating the socket factory
* @throws ConfigurationException on invalid configuration data
* @throws PKIException while initializing the IAIKX509TrustManager
*/
public static SSLSocketFactory getSSLSocketFactory(
String url,
String certStoreRootDirParam,
String trustStoreURL,
String acceptedServerCertURL,
String chainingMode,
boolean checkRevocation,
String clientKeyStoreURL,
String clientKeyStorePassword,
String clientKeyStoreType
)
throws IOException, GeneralSecurityException, SSLConfigurationException, PKIException {
Logger.debug("Get SSLSocketFactory for " + url);
// retrieve SSLSocketFactory if already created
SSLSocketFactory ssf = (SSLSocketFactory)sslSocketFactories.get(url);
if (ssf != null)
return ssf;
TrustManager[] tms = getTrustManagers(
certStoreRootDirParam,
chainingMode,
trustStoreURL,
acceptedServerCertURL,
checkRevocation);
KeyManager[] kms = getKeyManagers(
clientKeyStoreType, clientKeyStoreURL, clientKeyStorePassword);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(kms, tms, null);
ssf = ctx.getSocketFactory();
// store SSLSocketFactory
sslSocketFactories.put(url, ssf);
return ssf;
}
public static void removeSSLSocketFactory(String url) {
Logger.info("Remove SSLSocketFactory for URL " + url);
if (sslSocketFactories.containsKey(url))
sslSocketFactories.remove(url);
}
/**
* Loads the client key store from file and gets the
* KeyManager
s from a default KeyManagerFactory
,
* initialized from the given client key store.
* @param clientKeyStoreType key store type of clientKeyStore
* @param clientKeyStoreURL URL of key store containing keys to be used for
* client authentication; if null
, the default key store will be utilized
* @param clientKeyStorePassword password used to check the integrity of the client key store;
* if null
, it will not be checked
* @return KeyManager
s to be used for creating an
* SSLSocketFactory
utilizing the given client key store
* @throws IOException thrown while reading from the key store file
* @throws GeneralSecurityException thrown while initializing the
* default KeyManagerFactory
*/
public static KeyManager[] getKeyManagers (
String clientKeyStoreType,
String clientKeyStoreURL,
String clientKeyStorePassword)
throws IOException, GeneralSecurityException {
if (clientKeyStoreURL == null)
return null;
// Set up the KeyStore to use. We need to load the file into
// a KeyStore instance.
KeyStore clientKeyStore = KeyStoreUtils.loadKeyStore(
clientKeyStoreType, clientKeyStoreURL, clientKeyStorePassword);
return getKeyManagers(clientKeyStore, clientKeyStorePassword);
}
/**
* Gets the KeyManager
s from a default KeyManagerFactory
,
* initialized from the given client key store.
* @param clientKeyStore client key store
* @param clientKeyStorePassword if provided, it will be used to check
* the integrity of the client key store; if omitted, it will not be checked
* @return KeyManager
s to be used for creating an
* SSLSocketFactory
utilizing the given client key store
* @throws GeneralSecurityException thrown while initializing the
* default KeyManagerFactory
*/
public static KeyManager[] getKeyManagers (
KeyStore clientKeyStore,
String clientKeyStorePassword)
throws GeneralSecurityException {
if (clientKeyStore == null)
return null;
// Now we initialize the default KeyManagerFactory with this KeyStore
String alg=KeyManagerFactory.getDefaultAlgorithm();
KeyManagerFactory kmFact=KeyManagerFactory.getInstance(alg);
char[] password = null;
if (clientKeyStorePassword != null)
password = clientKeyStorePassword.toCharArray();
kmFact.init(clientKeyStore, password);
// And now get the KeyManagers
KeyManager[] kms=kmFact.getKeyManagers();
return kms;
}
/**
* Initializes an IAIKX509TrustManager
for a given trust store,
* using configuration data.
*
* @param conf MOA-ID configuration provider
* @param trustStoreURL trust store URL
* @param acceptedServerCertURL file URL pointing to directory containing accepted server SSL certificates
* @return TrustManager
array containing the IAIKX509TrustManager
* @throws ConfigurationException on invalid configuration data
* @throws IOException on data-reading problems
* @throws PKIException while initializing the IAIKX509TrustManager
*/
private static TrustManager[] getTrustManagers(String certStoreRootDirParam,
String chainingMode, String trustStoreURL, String acceptedServerCertURL,
boolean checkRevocation)
throws SSLConfigurationException, PKIException, IOException, GeneralSecurityException {
PKIConfiguration cfg = null;
if (! PKIFactory.getInstance().isAlreadyConfigured())
cfg = new PKIConfigurationImpl(certStoreRootDirParam, chainingMode);
PKIProfile profile = new PKIProfileImpl(trustStoreURL, checkRevocation);
// This call fixes a bug occuring when PKIConfiguration is
// initialized by the MOA-SP initialization code, in case
// MOA-SP is called by API
MOAIDTrustManager.initializeLoggingContext();
IAIKX509TrustManager tm = new MOAIDTrustManager(acceptedServerCertURL);
tm.init(cfg, profile);
return new TrustManager[] {tm};
}
}