/* tjws - SSLAcceptor.java
* Copyright (C) 1999-2007 Dmitriy Rogatkin. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Visit http://tjws.sourceforge.net to get the latest information
* about Rogatkin's products.
* $Id: SSLAcceptor.java,v 1.5 2009/12/10 04:30:51 dmitriy Exp $
* Created on Feb 21, 2007
* @author dmitriy
*/
package Acme.Serve;
import Acme.Serve.Serve.Acceptor;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* @deprecated See resteasy-undertow module.
*/
@Deprecated
public class SSLAcceptor implements Acceptor
{
private static final Logger LOG = Logger.getLogger(SSLAcceptor.class.getName());
public static final String ARG_ALGORITHM = "algorithm"; // SUNX509
public static final String ARG_CLIENTAUTH = "clientAuth"; // false
public static final String ARG_KEYSTOREFILE = "keystoreFile"; // System.getProperty("user.home") + File.separator + ".keystore";
public static final String ARG_KEYSTOREPASS = "keystorePass"; // KEYSTOREPASS
public static final String ARG_KEYSTORETYPE = "keystoreType"; // KEYSTORETYPE
public static final String ARG_KEYPASS = "keyPass"; //
public static final String ARG_PROTOCOL = "protocol"; // TLS
public static final String ARG_BACKLOG = Serve.ARG_BACKLOG;
public static final String ARG_IFADDRESS = "ifAddress";
public static final String ARG_PORT = "ssl-port";
public static final String PROTOCOL_HANDLER = "com.sun.net.ssl.internal.www.protocol";
/**
* The name of the system property containing a "|" delimited list of
* protocol handler packages.
*/
public static final String PROTOCOL_PACKAGES = "java.protocol.handler.pkgs";
/**
* Certificate encoding algorithm to be used.
*/
public final static String SUNX509 = "SunX509";
/**
* default SSL port
*/
public final static int PORT = 8443;
/**
* default backlog
*/
public final static int BACKLOG = 1000;
/**
* Storage type of the key store file to be used.
*/
public final static String KEYSTORETYPE = "JKS";
/**
* SSL protocol variant to use.
*/
public final static String TLS = "TLS";
/**
* SSL protocol variant to use.
*/
public static final String protocol = TLS;
/**
* Password for accessing the key store file.
*/
private static final String KEYSTOREPASS = "123456";
/**
* Pathname to the key store file to be used.
*/
protected String keystoreFile = System.getProperty("user.home") + File.separator + ".keystore";
protected ServerSocket socket;
private String getKeystoreFile()
{
return (this.keystoreFile);
}
public Socket accept() throws IOException
{
Socket result = socket.accept();
if (result != null)
result.setSoTimeout(5 * 60 * 1000);
return result;
}
public void destroy() throws IOException
{
try
{
socket.close();
}
finally
{
socket = null;
}
}
@SuppressWarnings(value = "unchecked")
public void init(Map inProperties, Map outProperties) throws IOException
{
javax.net.ssl.SSLServerSocketFactory sslSoc = null;
// init keystore
KeyStore keyStore = null;
FileInputStream istream = null;
String keystorePass = null;
try
{
String keystoreType = getWithDefault(inProperties, ARG_KEYSTORETYPE, KEYSTORETYPE);
keyStore = KeyStore.getInstance(keystoreType);
String keystoreFile = (String) inProperties.get(ARG_KEYSTOREFILE);
if (keystoreFile == null)
keystoreFile = getKeystoreFile();
istream = new FileInputStream(keystoreFile);
keystorePass = getWithDefault(inProperties, ARG_KEYSTOREPASS, KEYSTOREPASS);
keyStore.load(istream, keystorePass.toCharArray());
}
catch (Exception e)
{
LOG.log(Level.SEVERE, "initKeyStore: " + e, e);
throw new IOException(e.toString());
}
finally
{
if (istream != null)
istream.close();
}
try
{
String protocol = getWithDefault(inProperties, ARG_PROTOCOL, TLS);
SSLContext context;
try
{
// Create an SSL context used to create an SSL socket factory
context = SSLContext.getInstance(protocol);
}
catch (NoSuchAlgorithmException e)
{
// Register the JSSE security Provider (if it is not already there)
try
{
Security.addProvider((java.security.Provider) Class.forName("com.sun.net.ssl.internal.ssl.Provider")
.newInstance());
}
catch (Throwable t)
{
LOG.log(Level.SEVERE, t.getMessage(), t);
throw new IOException(t.toString());
}
// Create an SSL context used to create an SSL socket factory
context = SSLContext.getInstance(protocol);
}
// Create the key manager factory used to extract the server key
String algorithm = getWithDefault(inProperties, ARG_ALGORITHM, SUNX509);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(algorithm);
String keyPass = getWithDefault(inProperties, ARG_KEYPASS, keystorePass);
keyManagerFactory.init(keyStore, keyPass.toCharArray());
// Initialize the context with the key managers
context.init(keyManagerFactory.getKeyManagers(), null, new java.security.SecureRandom());
// Create the proxy and return
sslSoc = context.getServerSocketFactory();
}
catch (Exception e)
{
LOG.log(Level.SEVERE, "SSLsocket creation: " + e, e);
throw new IOException(e.toString());
}
int port = PORT;
if (inProperties.get(ARG_PORT) != null)
try
{
port = Integer.parseInt((String) inProperties.get(ARG_PORT));
}
catch (NumberFormatException nfe)
{
}
else if (inProperties.get(Serve.ARG_PORT) != null)
port = ((Integer) inProperties.get(Serve.ARG_PORT)).intValue();
if (inProperties.get(ARG_BACKLOG) == null)
if (inProperties.get(ARG_IFADDRESS) == null)
socket = sslSoc.createServerSocket(port);
else
socket = sslSoc.createServerSocket(port, BACKLOG, InetAddress.getByName((String) inProperties
.get(ARG_IFADDRESS)));
else if (inProperties.get(ARG_IFADDRESS) == null)
socket = sslSoc.createServerSocket(port, new Integer((String) inProperties.get(ARG_BACKLOG)).intValue());
else
socket = sslSoc.createServerSocket(port, new Integer((String) inProperties.get(ARG_BACKLOG)).intValue(), InetAddress
.getByName((String) inProperties.get(ARG_IFADDRESS)));
initServerSocket(socket, "true".equals(inProperties.get(ARG_CLIENTAUTH)));
if (outProperties != null)
outProperties.put(Serve.ARG_BINDADDRESS, socket.getInetAddress().getHostName());
}
/**
* Register our URLStreamHandler for the "https:" protocol.
*/
protected static void initHandler()
{
String packages = System.getProperty(PROTOCOL_PACKAGES);
if (packages == null)
packages = PROTOCOL_HANDLER;
else if (packages.indexOf(PROTOCOL_HANDLER) < 0)
packages += "|" + PROTOCOL_HANDLER;
System.setProperty(PROTOCOL_PACKAGES, packages);
}
public String toString()
{
return socket != null ? socket.toString() : "SSLAcceptor uninitialized";
}
static
{
initHandler();
}
/**
* Set the requested properties for this server socket.
*
* @param ssocket The server socket to be configured
*/
protected void initServerSocket(ServerSocket ssocket, boolean clientAuth)
{
SSLServerSocket socket = (SSLServerSocket) ssocket;
// Enable all available cipher suites when the socket is connected
String cipherSuites[] = socket.getSupportedCipherSuites();
socket.setEnabledCipherSuites(cipherSuites);
// Set client authentication if necessary
socket.setNeedClientAuth(clientAuth);
}
private String getWithDefault(Map args, String name, String defValue)
{
String result = (String) args.get(name);
if (result == null)
return defValue;
return result;
}
}