package at.gv.egovernment.moa.id.util; import iaik.pki.PKIConfiguration; import iaik.pki.PKIException; import iaik.pki.PKIFactory; import iaik.pki.PKIProfile; import iaik.pki.jsse.IAIKX509TrustManager; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.security.GeneralSecurityException; import java.security.Security; import java.util.HashMap; import java.util.Map; import javax.net.ssl.SSLSocketFactory; import at.gv.egovernment.moa.id.config.ConfigurationException; import at.gv.egovernment.moa.id.config.ConfigurationProvider; import at.gv.egovernment.moa.id.config.ConnectionParameter; import at.gv.egovernment.moa.id.iaik.config.PKIConfigurationImpl; import at.gv.egovernment.moa.id.iaik.pki.PKIProfileImpl; import at.gv.egovernment.moa.id.iaik.pki.jsse.MOAIDTrustManager; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.StreamUtils; import com.sun.net.ssl.HttpsURLConnection; import com.sun.net.ssl.KeyManager; import com.sun.net.ssl.SSLContext; import com.sun.net.ssl.TrustManager; /** * Utility for a obtaining a secure socket factory using IAIKX509TrustManager. * This TrustManager implementation features CRL checking.
* SSLUtils caches secure socket factories for given ConnectionParameters. * * @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(); Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); 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( ConfigurationProvider conf, ConnectionParameter connParam) throws IOException, GeneralSecurityException, ConfigurationException, PKIException { Logger.debug("Get SSLSocketFactory for " + connParam.getUrl()); // retrieve SSLSocketFactory if already created SSLSocketFactory ssf = (SSLSocketFactory)sslSocketFactories.get(connParam.getUrl()); if (ssf != null) return ssf; // else create new SSLSocketFactory String trustStoreURL = conf.getTrustedCACertificates(); if (trustStoreURL == null) throw new ConfigurationException( "config.08", new Object[] {"TrustedCACertificates"}); String acceptedServerCertURL = connParam.getAcceptedServerCertificates(); TrustManager[] tms = getTrustManagers(conf, trustStoreURL, acceptedServerCertURL); KeyManager[] kms = at.gv.egovernment.moa.util.SSLUtils.getKeyManagers( "pkcs12", connParam.getClientKeyStore(), connParam.getClientKeyStorePassword()); SSLContext ctx = SSLContext.getInstance("TLS"); ctx.init(kms, tms, null); ssf = ctx.getSocketFactory(); // store SSLSocketFactory sslSocketFactories.put(connParam.getUrl(), ssf); return ssf; } /** * 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 */ public static TrustManager[] getTrustManagers( ConfigurationProvider conf, String trustStoreURL, String acceptedServerCertURL) throws ConfigurationException, PKIException, IOException, GeneralSecurityException { PKIConfiguration cfg = null; if (! PKIFactory.getInstance().isAlreadyConfigured()) cfg = new PKIConfigurationImpl(conf); PKIProfile profile = new PKIProfileImpl(trustStoreURL); // 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}; } /** * 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 file 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 byte[] 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(); InputStream in = new BufferedInputStream(conn.getInputStream()); byte[] content = StreamUtils.readStream(in); in.close(); conn.disconnect(); return content; } }