/*******************************************************************************
* 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.util;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.security.GeneralSecurityException;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;
import org.apache.regexp.RE;
import org.apache.regexp.RESyntaxException;
import at.gv.egovernment.moa.id.commons.api.AuthConfiguration;
import at.gv.egovernment.moa.id.commons.api.ConfigurationProvider;
import at.gv.egovernment.moa.id.commons.api.ConnectionParameterInterface;
import at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException;
import at.gv.egovernment.moa.id.commons.utils.ssl.SSLConfigurationException;
import at.gv.egovernment.moa.id.config.ConnectionParameter;
import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;
import iaik.pki.PKIException;
/**
* 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 {
public static void initialize() {
// 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");
}
public static SSLSocketFactory getSSLSocketFactory(
ConfigurationProvider conf, String url )
throws IOException, GeneralSecurityException, ConfigurationException, PKIException {
boolean useStandardJavaTrustStore = conf.getBasicConfigurationBoolean(
AuthConfiguration.PROP_KEY_SSL_USE_JVM_TRUSTSTORE,
false);
// else create new SSLSocketFactory
String trustStoreURL = conf.getTrustedCACertificates();
if (trustStoreURL == null)
throw new ConfigurationException(
"config.08", new Object[] {"TrustedCACertificates"});
String acceptedServerCertURL = "";
//INFO: MOA-ID 2.x always use defaultChainingMode
try {
SSLSocketFactory ssf = at.gv.egovernment.moa.id.commons.utils.ssl.SSLUtils.getSSLSocketFactory(
url,
useStandardJavaTrustStore,
null,
trustStoreURL,
acceptedServerCertURL,
AuthConfigurationProviderFactory.getInstance().getDefaultChainingMode(),
AuthConfigurationProviderFactory.getInstance().isTrustmanagerrevoationchecking(),
AuthConfigurationProviderFactory.getInstance().getRevocationMethodOrder(),
null,
null,
"pkcs12");
return ssf;
} catch (SSLConfigurationException e) {
throw new ConfigurationException(e.getErrorID(), e.getParameters(), e.getE());
}
}
/**
* 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(
ConfigurationProvider conf,
ConnectionParameterInterface connParam)
throws IOException, GeneralSecurityException, ConfigurationException, PKIException {
boolean useStandardJavaTrustStore = conf.getBasicConfigurationBoolean(
AuthConfiguration.PROP_KEY_SSL_USE_JVM_TRUSTSTORE,
false);
// else create new SSLSocketFactory
String trustStoreURL = conf.getTrustedCACertificates();
if (trustStoreURL == null)
throw new ConfigurationException(
"config.08", new Object[] {"TrustedCACertificates"});
String acceptedServerCertURL = connParam.getAcceptedServerCertificates();
//INFO: MOA-ID 2.x always use defaultChainingMode
try {
SSLSocketFactory ssf = at.gv.egovernment.moa.id.commons.utils.ssl.SSLUtils.getSSLSocketFactory(
connParam.getUrl(),
useStandardJavaTrustStore,
null,
trustStoreURL,
acceptedServerCertURL,
AuthConfigurationProviderFactory.getInstance().getDefaultChainingMode(),
AuthConfigurationProviderFactory.getInstance().isTrustmanagerrevoationchecking(),
AuthConfigurationProviderFactory.getInstance().getRevocationMethodOrder(),
connParam.getClientKeyStore(),
connParam.getClientKeyStorePassword(),
"pkcs12");
return ssf;
} catch (SSLConfigurationException e) {
throw new ConfigurationException(e.getErrorID(), e.getParameters(), e.getE());
}
}
/**
* Reads a file, given by URL, into a byte array,
* securing the connection by IAIKX509TrustManager.
* @param connParam containing URL and accepted server certificates
* @param conf ConfigurationProvider for reading
* @return String representation of content
* @throws ConfigurationException on invalid configuration data
* @throws PKIException on invalid configuration data
* @throws IOException on data-reading problems
* @throws GeneralSecurityException on security issues
*/
public static String readHttpsURL(ConfigurationProvider conf, ConnectionParameter connParam)
throws ConfigurationException, PKIException, IOException, GeneralSecurityException {
URL url = new URL(connParam.getUrl());
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.setRequestMethod("GET");
conn.setDoInput(true);
SSLSocketFactory sslSocketFactory = getSSLSocketFactory(conf, connParam);
conn.setSSLSocketFactory(sslSocketFactory);
conn.connect();
String contentType = conn.getContentType();
RE regExp = null;
try {
regExp = new RE("(;.*charset=)(\"*)(.*[^\"])");
} catch (RESyntaxException e) {
//RESyntaxException is not possible = expr. is costant
}
boolean charsetSupplied = regExp.match(contentType);
String encoding = "ISO-8859-1"; //default HTTP encoding
if (charsetSupplied) {
encoding = regExp.getParen(3);
}
InputStream instream = new BufferedInputStream(conn.getInputStream());
InputStreamReader isr = new InputStreamReader(instream, encoding);
Reader in = new BufferedReader(isr);
int ch;
StringBuffer buffer = new StringBuffer();
while ((ch = in.read()) > -1) {
buffer.append((char)ch);
}
in.close();
conn.disconnect();
return buffer.toString();
}
}