/*
* Copyright (c) 2013 Big Switch Networks, Inc.
*
* Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html
*
* 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 org.sdnplatform.ovsdb.internal;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.Security;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import org.jboss.netty.handler.ssl.SslHandler;
/**
* Sends client and server certificates and accepts all certificates
* presented to us without any verification.
*
* TODO: Use logger for error handling.
* TODO: Handle keystore locations.
* TODO: Error handling if keystore doesn't exists.
* Maybe use a Singleton instance instead of static initializtion?
*
* <h3>Client Certificate Authentication</h3>
*
* To enable client certificate authentication:
* <ul>
* <li>Enable client authentication on the server side by calling
* {@link SSLEngine#setNeedClientAuth(boolean)} before creating
* {@link SslHandler}.</li>
* <li>When initializing an {@link SSLContext} on the client side,
* specify the {@link KeyManager} that contains the client certificate as
* the first argument of {@link SSLContext#init(KeyManager[], javax.net.ssl.TrustManager[], java.security.SecureRandom)}.</li>
* <li>When initializing an {@link SSLContext} on the server side,
* specify the proper {@link TrustManager} as the second argument of
* {@link SSLContext#init(KeyManager[], javax.net.ssl.TrustManager[], java.security.SecureRandom)}
* to validate the client certificate.</li>
* </ul>
*/
public class BSNSslContextFactory {
private static final String PROTOCOL = "SSL";
private static final SSLContext SERVER_CONTEXT;
private static final SSLContext CLIENT_CONTEXT;
static {
String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm");
if (algorithm == null) {
algorithm = "SunX509";
}
/**
* The following makes sure we do not do any certificate validation when
* we create a HTTPS connection.
*/
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
}
public void checkServerTrusted(X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
}
} };
SSLContext serverContext = null;
SSLContext clientContext = null;
//char[] password = "password".toCharArray();
char[] password = "importkey".toCharArray();
try {
KeyStore ks = KeyStore.getInstance("JKS");
InputStream is = new java.io.FileInputStream("/Users/gregor/work/master/keystore.jks");
ks.load(is, password);
is.close();
// Set up key manager factory to use our key store
KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
kmf.init(ks, password);
// Initialize the SSLContext to work with our key managers.
// Instead of using trustAllCerts we can also just use null
serverContext = SSLContext.getInstance(PROTOCOL);
serverContext.init(kmf.getKeyManagers(), trustAllCerts, null);
clientContext = SSLContext.getInstance(PROTOCOL);
clientContext.init(kmf.getKeyManagers(), trustAllCerts, null);
} catch (Exception e) {
// TODO: error handling is broken!
throw new Error("Failed to initialize the SSLContexts", e);
}
finally {
Arrays.fill(password, '\0');
}
SERVER_CONTEXT = serverContext;
CLIENT_CONTEXT = clientContext;
}
public static SSLContext getServerContext() {
return SERVER_CONTEXT;
}
public static SSLContext getClientContext() {
return CLIENT_CONTEXT;
}
}