/* * Copyright 2011 Federal Chancellery Austria and * Graz University of Technology * * Licensed 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 at.gv.util.ssl; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.util.Properties; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import at.gv.util.TrustAllManager; import at.gv.util.ex.EgovUtilException; /** * Some utility methods for SSL handling. * * @author Arne Tauber * */ public class SSLUtils { private static Logger log = LoggerFactory.getLogger(SSLUtils.class); public static boolean useLaxHostNameVerifier(Properties props, String propsPrefix) { try { return Boolean.parseBoolean(props.getProperty(propsPrefix + ".ssl.laxhostnameverification")); } catch(Exception e) { return false; } } public static SSLContext getPropertiesSSLContext(Properties props, String configDir, String propsPrefix, boolean forceTrustAllManager) throws EgovUtilException { log.trace("Configuring SSL socket factory."); if (props == null) { throw new NullPointerException("Argument 'properties' must not be null."); } if (configDir == null) { throw new NullPointerException("Argument 'configDir' must not be null."); } boolean hasSSLConfigured = props.getProperty(propsPrefix + ".ssl.keystore.file") != null || props.getProperty(propsPrefix + ".ssl.truststore.file") != null || "true".equalsIgnoreCase(props.getProperty(propsPrefix + ".ssl.trustall")); log.trace("SSL enabled: " + hasSSLConfigured); if (hasSSLConfigured) { log.trace("Configuring using standard JKS or PKCS12 keystore/truststore."); try { SSLContext context = SSLContext.getInstance("TLS"); // load client key store KeyManager[] keyManager = null; if (props.getProperty(propsPrefix + ".ssl.keystore.file") != null) { log.trace("Keystore definition found."); String keyStoreFileName = props.getProperty(propsPrefix + ".ssl.keystore.file"); File keyTmp = new File(keyStoreFileName); File keyStoreFile = null; if (keyTmp.isAbsolute()) { keyStoreFile = keyTmp; } else { keyStoreFile = new File(configDir, keyStoreFileName); } log.trace("Key store location: " + keyStoreFile); String keyStorePassword = props.getProperty(propsPrefix + ".ssl.keystore.password"); if (keyStorePassword == null) { log.trace("No keystore password set in configuration, using empty password."); keyStorePassword = ""; } String keyStoreType = props.getProperty(propsPrefix + ".ssl.keystore.type"); if (keyStoreType == null) { log.trace("No keystore type set in configuration, using default JKS."); keyStoreType = "JKS"; } log.trace("Key store type: " + keyStoreType); KeyStore clientStore = KeyStore.getInstance(keyStoreType); clientStore.load(new FileInputStream(keyStoreFile), keyStorePassword.toCharArray()); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(clientStore, keyStorePassword.toCharArray()); keyManager = kmf.getKeyManagers(); } else { log.trace("No keystore definition found. Not using SSL client authentication."); } // load trust store TrustManager[] trustManager = null; if (forceTrustAllManager || "true".equalsIgnoreCase(props.getProperty(propsPrefix + ".ssl.trustall"))) { log.info("Trust all property is switched on. This setting is not recommended."); trustManager = new TrustManager[] { new TrustAllManager() }; } else if (props.getProperty(propsPrefix + ".ssl.truststore.file") != null) { log.trace("Using standard trust store mechanism (truststore file definition found)."); String trustStoreFileName = props.getProperty(propsPrefix + ".ssl.truststore.file"); File trustTmp = new File(trustStoreFileName); File trustStoreFile = null; if (trustTmp.isAbsolute()) { trustStoreFile = trustTmp; } else { trustStoreFile = new File(configDir, trustStoreFileName); } log.trace("Trust store file location: " + trustStoreFile); if (trustStoreFile == null) { throw new EgovUtilException("Please set a trust store in your configuration or switch the trust all property on."); } String trustStorePassword = props.getProperty(propsPrefix + ".ssl.truststore.password"); if (trustStorePassword == null) { log.trace("No truststore password set in configuration, using empty password."); trustStorePassword = ""; } String trustStoreType = props.getProperty(propsPrefix + ".ssl.truststore.type"); if (trustStoreType == null) { log.trace("No truststore type set in configuration, using default JKS."); trustStoreType = "JKS"; } log.trace("Trust store type: " + trustStoreType); KeyStore trustStore = KeyStore.getInstance(trustStoreType); trustStore.load(new FileInputStream(trustStoreFile), trustStorePassword.toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(trustStore); trustManager = tmf.getTrustManagers(); } else { log.warn("No truststore definition found. Using standard Java truststore mechanism."); } context.init(keyManager, trustManager, new SecureRandom()); return context; } catch (NoSuchAlgorithmException e) { throw new EgovUtilException(e); } catch (KeyStoreException e) { throw new EgovUtilException(e); } catch (CertificateException e) { throw new EgovUtilException(e); } catch (FileNotFoundException e) { throw new EgovUtilException(e); } catch (IOException e) { throw new EgovUtilException(e); } catch (UnrecoverableKeyException e) { throw new EgovUtilException(e); } catch (KeyManagementException e) { throw new EgovUtilException(e); } } else { throw new EgovUtilException("Please provide an SSL configuration in your properties file."); } } }