/*
* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.management.jmxremote;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.rmi.ssl.SslRMIServerSocketFactory;
/**
* This class represents a specialized version of the
* <code>SslRMIServerSocketFactory</code> class that
* allows to supply an <code>SSLContext</code>.
*
* @see javax.rmi.ssl.SslRMIServerSocketFactory
*/
public class SSLContextRMIServerSocketFactory extends SslRMIServerSocketFactory {
/**
* <p>Creates a new <code>SSLContextRMIServerSocketFactory</code> with
* SSL sockets created from the <code>SSLSocketFactory</code> returned
* by the given <code>SSLContext</code> and configured with the default
* SSL parameters.
*
* <p>SSL connections accepted by server sockets created by this
* factory have the default cipher suites and protocol versions
* enabled and do not require client authentication.</p>
*
* @param context the SSL context to be used for creating SSL sockets.
* Calling this constructor with a null <code>context</code> is equivalent
* to calling <code>SslRMIServerSocketFactory()</code>.
*/
public SSLContextRMIServerSocketFactory(SSLContext context) {
this(context, null, null, false);
}
/**
* <p>Creates a new <code>SSLContextRMIServerSocketFactory</code> with
* SSL sockets created from the <code>SSLSocketFactory</code> returned
* by the given <code>SSLContext</code> and configured with the supplied
* SSL parameters.
*
* @param context the SSL context to be used for creating SSL sockets.
* Calling this constructor with a null <code>context</code> is equivalent
* to calling <code>SslRMIServerSocketFactory(enabledCipherSuites,
* enabledProtocols, needClientAuth)</code>.
*
* @param enabledCipherSuites names of all the cipher suites to
* enable on SSL connections accepted by server sockets created by
* this factory, or <code>null</code> to use the cipher suites
* that are enabled by default
*
* @param enabledProtocols names of all the protocol versions to
* enable on SSL connections accepted by server sockets created by
* this factory, or <code>null</code> to use the protocol versions
* that are enabled by default
*
* @param needClientAuth <code>true</code> to require client
* authentication on SSL connections accepted by server sockets
* created by this factory; <code>false</code> to not require
* client authentication
*
* @exception IllegalArgumentException when one or more of the cipher
* suites named by the <code>enabledCipherSuites</code> parameter is
* not supported, when one or more of the protocols named by the
* <code>enabledProtocols</code> parameter is not supported or when
* a problem is encountered while trying to check if the supplied
* cipher suites and protocols to be enabled are supported.
*
* @see SSLSocket#setEnabledCipherSuites
* @see SSLSocket#setEnabledProtocols
* @see SSLSocket#setNeedClientAuth
*/
public SSLContextRMIServerSocketFactory(
SSLContext context,
String[] enabledCipherSuites,
String[] enabledProtocols,
boolean needClientAuth)
throws IllegalArgumentException {
super(enabledCipherSuites, enabledProtocols, needClientAuth);
this.context = context;
// NOTE: We should check the availability of the enabledCipherSuites
// and enabledProtocols in the socket factory returned by the call
// context.getSocketFactory() because it could differ from the one
// returned by SSLSocketFactory.getDefault(), which is already
// checked in the parent's class constructor, but we don't do it
// because we know that although the factory the out-of-the-box
// management agent uses might be different, they are of the same
// type and use the same underlying SSLSocket implementation.
}
/**
* <p>Creates a server socket that accepts SSL connections configured
* according to this factory's SSL socket configuration parameters.
* If a null <code>SSLContext</code> was supplied in the constructor
* this method just calls <code>super.createServerSocket(port)</code>.
* Otherwise, the <code>SSLSocketFactory</code> returned by the call to
* <code>SSLContext.getSocketFactory()</code> will be used to create the
* SSL sockets.</p>
*/
@Override
public ServerSocket createServerSocket(int port) throws IOException {
if (context == null) {
return super.createServerSocket(port);
} else {
final SSLSocketFactory sslSocketFactory = context.getSocketFactory();
return new ServerSocket(port) {
public Socket accept() throws IOException {
Socket socket = super.accept();
SSLSocket sslSocket = (SSLSocket)
sslSocketFactory.createSocket(
socket, socket.getInetAddress().getHostName(),
socket.getPort(), true);
sslSocket.setUseClientMode(false);
if (getEnabledCipherSuites() != null) {
sslSocket.setEnabledCipherSuites(getEnabledCipherSuites());
}
if (getEnabledProtocols() != null) {
sslSocket.setEnabledProtocols(getEnabledProtocols());
}
sslSocket.setNeedClientAuth(getNeedClientAuth());
return sslSocket;
}
};
}
}
/**
* <p>Indicates whether some other object is "equal to" this one.</p>
*
* <p>Two <code>SSLContextRMIServerSocketFactory</code> objects are
* equal if they have been constructed with the same SSL context and
* SSL socket configuration parameters.</p>
*
* <p>A subclass should override this method (as well as
* {@link #hashCode()}) if it adds instance state that affects
* equality.</p>
*/
@Override
public boolean equals(Object obj) {
if (!super.equals(obj))
return false;
SSLContextRMIServerSocketFactory that = (SSLContextRMIServerSocketFactory) obj;
return context == null ? that.context == null : context.equals(that.context);
}
/**
* <p>Returns a hash code value for this
* <code>SSLContextRMIServerSocketFactory</code>.</p>
*
* @return a hash code value for this
* <code>SSLContextRMIServerSocketFactory</code>.
*/
@Override
public int hashCode() {
return super.hashCode() + (context == null ? 0 : context.hashCode());
}
private SSLContext context;
}