/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you 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 org.jboss.aerogear.simplepush.server.netty;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.Security;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import org.jboss.aerogear.io.netty.handler.codec.sockjs.SockJsConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Creates a {@link SSLContext} for just server certificates.
*/
public final class WebSocketSslServerSslContext {
private static final String PROTOCOL = "TLS";
private final SockJsConfig sockJsConfig;
private final Logger logger = LoggerFactory.getLogger(SimplePushSockJSService.class);
WebSocketSslServerSslContext(final SockJsConfig sockJsConfig) {
this.sockJsConfig = sockJsConfig;
}
/**
* Creates a new {@link SSLContext}. This is an expensive operation and should only be done
* once and then the SSL connectContext can be reused.
*
* @return {@link SSLContext} the SSLContext.
*/
public SSLContext sslContext() {
try {
final SSLContext serverContext = SSLContext.getInstance(PROTOCOL);
serverContext.init(keyManagerFactory(loadKeyStore()).getKeyManagers(), null, null);
return serverContext;
} catch (final Exception e) {
throw new RuntimeException("Failed to initialize the server-side SSLContext", e);
}
}
private KeyManagerFactory keyManagerFactory(final KeyStore ks) throws Exception {
final KeyManagerFactory kmf = KeyManagerFactory.getInstance(getKeyManagerAlgorithm());
kmf.init(ks, sockJsConfig.keyStorePassword().toCharArray());
return kmf;
}
@SuppressWarnings("resource")
private KeyStore loadKeyStore() throws Exception {
InputStream fin = null;
try {
fin = this.getClass().getResourceAsStream(sockJsConfig.keyStore());
if (fin == null) {
throw new IllegalStateException("Could not locate keystore [" + sockJsConfig.keyStore() + "]");
}
final KeyStore ks = KeyStore.getInstance("JKS");
ks.load(fin, sockJsConfig.keyStorePassword().toCharArray());
return ks;
} finally {
safeClose(fin);
}
}
private String getKeyManagerAlgorithm() {
String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm");
if (algorithm == null) {
algorithm = "SunX509";
}
return algorithm;
}
private void safeClose(final Closeable c) {
try {
if (c != null) {
c.close();
}
} catch (final IOException e) {
logger.error("Error while trying to close closable [" + c + "]", e);
}
}
}