/* * Copyright (c) 2008-2010 by Bjoern Kolbeck, Jan Stender, Christian Lorenz, * Zuse Institute Berlin * * Licensed under the BSD License, see LICENSE file for details. * */ package de.mxro.thrd.xstreemfs.foundation; import java.io.IOException; import java.io.InputStream; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; /** * Encapsulates the SSLOptions for the connections of pinky and speedy * * @author clorenz */ public class SSLOptions { /** * a Java JKS Keystore */ public final static String JKS_CONTAINER = "JKS"; /** * a PKCS12 Keystore */ public final static String PKCS12_CONTAINER = "PKCS12"; /** * file with the private key and the public cert for the server */ private final InputStream serverCredentialFile; /** * file with trusted public certs */ private final InputStream trustedCertificatesFile; /** * passphrase of the server credential file */ private final char[] serverCredentialFilePassphrase; /** * passphrase of the trusted certificates file */ private final char[] trustedCertificatesFilePassphrase; /** * using symmetric encryption or only authenticating via certs */ private boolean authenticationWithoutEncryption; /** * file format of the server credential file */ private final String serverCredentialFileContainer; /** * file format of the trusted certificates file */ private final String trustedCertificatesFileContainer; /** * knows the used certs and more */ private final SSLContext sslContext; private final boolean useFakeSSLMode; /** * creates a new SSLOptions object, which uses PKCS12 Container and * symmetric encryption * * @param serverCredentialFile * file with the private key and the public cert for the server * @param serverCredentialFilePassphrase * passphrase of the server credential file * @param trustedCertificatesFile * file with trusted public certs * @param trustedCertificatesFilePassphrase * passphrase of the trusted certificates file * @throws IOException */ public SSLOptions(InputStream serverCredentialFile, String serverCredentialFilePassphrase, InputStream trustedCertificatesFile, String trustedCertificatesFilePassphrase) throws IOException { this(serverCredentialFile, serverCredentialFilePassphrase, PKCS12_CONTAINER, trustedCertificatesFile, trustedCertificatesFilePassphrase, JKS_CONTAINER, false); } /** * creates a new SSLOptions object * * @param serverCredentialFile * file with the private key and the public cert for the server * @param serverCredentialFilePassphrase * passphrase of the server credential file * @param serverCredentialFileContainer * file format of the server credential file * @param trustedCertificatesFile * file with trusted public certs * @param trustedCertificatesFilePassphrase * passphrase of the trusted certificates file * @param trustedCertificatesFileContainer * file format of the trusted certificates file * @param authenticationWithoutEncryption * using symmetric encryption or only authenticating via certs * @throws IOException */ public SSLOptions(InputStream serverCredentialFile, String serverCredentialFilePassphrase, String serverCredentialFileContainer, InputStream trustedCertificatesFile, String trustedCertificatesFilePassphrase, String trustedCertificatesFileContainer, boolean authenticationWithoutEncryption) throws IOException { this(serverCredentialFile, serverCredentialFilePassphrase, serverCredentialFileContainer, trustedCertificatesFile, trustedCertificatesFilePassphrase, trustedCertificatesFileContainer, authenticationWithoutEncryption, false, null); } public SSLOptions(InputStream serverCredentialFile, String serverCredentialFilePassphrase, String serverCredentialFileContainer, InputStream trustedCertificatesFile, String trustedCertificatesFilePassphrase, String trustedCertificatesFileContainer, boolean authenticationWithoutEncryption, boolean useFakeSSLMode, TrustManager trustManager) throws IOException { this.serverCredentialFile = serverCredentialFile; this.trustedCertificatesFile = trustedCertificatesFile; if (serverCredentialFilePassphrase != null) this.serverCredentialFilePassphrase = serverCredentialFilePassphrase.toCharArray(); else this.serverCredentialFilePassphrase = null; if (trustedCertificatesFilePassphrase != null) this.trustedCertificatesFilePassphrase = trustedCertificatesFilePassphrase.toCharArray(); else this.trustedCertificatesFilePassphrase = null; this.serverCredentialFileContainer = serverCredentialFileContainer; this.trustedCertificatesFileContainer = trustedCertificatesFileContainer; this.authenticationWithoutEncryption = authenticationWithoutEncryption; this.useFakeSSLMode = useFakeSSLMode; sslContext = createSSLContext(trustManager); } /** * Create/initialize the SSLContext with key material * * @param trustManager * the trust manager for the SSL context (may be * <code>null</code>) * @return the created and initialized SSLContext * @throws IOException */ private SSLContext createSSLContext(TrustManager trustManager) throws IOException { SSLContext sslContext = null; try { // First initialize the key and trust material. KeyStore ksKeys = KeyStore.getInstance(serverCredentialFileContainer); ksKeys.load(serverCredentialFile, serverCredentialFilePassphrase); // KeyManager's decide which key material to use. KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ksKeys, serverCredentialFilePassphrase); sslContext = SSLContext.getInstance("TLS"); if (trustManager != null) { // if a user-defined trust manager is set ... trustManager.init(trustedCertificatesFileContainer, trustedCertificatesFile, trustedCertificatesFilePassphrase); sslContext.init(kmf.getKeyManagers(), new TrustManager[] { trustManager }, null); } else if (trustedCertificatesFileContainer.equals("none")) { TrustManager[] myTMs = new TrustManager[] { new NoAuthTrustStore() }; sslContext.init(kmf.getKeyManagers(), myTMs, null); } else { // TrustManager's decide whether to allow connections. KeyStore ksTrust = null; if (trustedCertificatesFileContainer.equals("none")) { ksTrust = KeyStore.getInstance(KeyStore.getDefaultType()); } else { ksTrust = KeyStore.getInstance(trustedCertificatesFileContainer); ksTrust.load(trustedCertificatesFile, trustedCertificatesFilePassphrase); } TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(ksTrust); sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); } } catch (UnrecoverableKeyException e) { e.printStackTrace(); } catch (KeyManagementException e) { e.printStackTrace(); } catch (KeyStoreException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (CertificateException e) { e.printStackTrace(); } return sslContext; } public boolean isAuthenticationWithoutEncryption() { return this.authenticationWithoutEncryption; } public void setAuthenticationWithoutEncryption(boolean authenticationWithoutEncryption) { this.authenticationWithoutEncryption = authenticationWithoutEncryption; } public InputStream getServerCredentialFile() { return this.serverCredentialFile; } public String getServerCredentialFileContainer() { return this.serverCredentialFileContainer; } public String getServerCredentialFilePassphrase() { return this.serverCredentialFilePassphrase.toString(); } public InputStream getTrustedCertificatesFile() { return this.trustedCertificatesFile; } public String getTrustedCertificatesFileContainer() { return this.trustedCertificatesFileContainer; } public String getTrustedCertificatesFilePassphrase() { return this.trustedCertificatesFilePassphrase.toString(); } public SSLContext getSSLContext() { return this.sslContext; } public boolean isFakeSSLMode() { return this.useFakeSSLMode; } private static class NoAuthTrustStore implements TrustManager, X509TrustManager { @Override public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { // ignore } @Override public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { // ignore } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[] {}; } @Override public void init(String trustedCertificatesFileContainer, InputStream trustedCertificatesFile, char[] trustedCertificatesFilePassphrase) { // ignore } } public static interface TrustManager extends javax.net.ssl.TrustManager { public void init(String trustedCertificatesFileContainer, InputStream trustedCertificatesFile, char[] trustedCertificatesFilePassphrase); } }