001 /*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License"). You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2006-2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.protocols.jmx;
028
029 import static org.opends.server.loggers.debug.DebugLogger.*;
030 import org.opends.server.loggers.debug.DebugTracer;
031
032 import java.io.IOException;
033 import java.net.InetAddress;
034 import java.net.ServerSocket;
035 import java.net.Socket;
036 import java.rmi.server.RMIServerSocketFactory;
037
038 import javax.net.ssl.SSLSocket;
039 import javax.net.ssl.SSLSocketFactory;
040
041 /**
042 * A <code>DirectoryRMIServerSocketFactory</code> instance is used by the RMI
043 * runtime in order to obtain server sockets for RMI calls via SSL.
044 *
045 * <p>
046 * This class implements <code>RMIServerSocketFactory</code> over the Secure
047 * Sockets Layer (SSL) or Transport Layer Security (TLS) protocols.
048 * </p>
049 */
050 public class DirectoryRMIServerSocketFactory implements
051 RMIServerSocketFactory
052 {
053 /**
054 * The tracer object for the debug logger.
055 */
056 private static final DebugTracer TRACER = getTracer();
057
058 /**
059 * The SSL socket factory associated with the connector.
060 */
061 private SSLSocketFactory sslSocketFactory = null;
062
063 /**
064 * Indicate if we required the client authentication via SSL.
065 */
066 private final boolean needClientCertificate;
067
068
069 /**
070 * Constructs a new <code>DirectoryRMIServerSocketFactory</code> with the
071 * specified SSL socket configuration.
072 *
073 * @param sslSocketFactory
074 * the SSL socket factory to be used by this factory
075 *
076 * @param needClientCertificate
077 * <code>true</code> to require client authentication on SSL
078 * connections accepted by server sockets created by this
079 * factory; <code>false</code> to not require client
080 * authentication.
081 */
082 public DirectoryRMIServerSocketFactory(SSLSocketFactory sslSocketFactory,
083 boolean needClientCertificate)
084 {
085 //
086 // Initialize the configuration parameters.
087 this.needClientCertificate = needClientCertificate;
088 this.sslSocketFactory = sslSocketFactory;
089 }
090
091 /**
092 * <p>
093 * Returns <code>true</code> if client authentication is required on SSL
094 * connections accepted by server sockets created by this factory.
095 * </p>
096 *
097 * @return <code>true</code> if client authentication is required
098 *
099 * @see SSLSocket#setNeedClientAuth
100 */
101 public final boolean getNeedClientCertificate()
102 {
103 return needClientCertificate;
104 }
105
106 /**
107 * Creates a server socket that accepts SSL connections configured according
108 * to this factory's SSL socket configuration parameters.
109 *
110 * @param port
111 * the port number the socket listens to
112 *
113 * @return a server socket
114 *
115 * @throws IOException
116 * if the socket cannot be created
117 */
118 public ServerSocket createServerSocket(int port) throws IOException
119 {
120 return new ServerSocket(port, 0, InetAddress.getByName("0.0.0.0"))
121 {
122 @Override
123 public Socket accept() throws IOException
124 {
125 Socket socket = super.accept();
126 if (debugEnabled())
127 {
128 TRACER.debugVerbose("host/port: %s/%d",
129 socket.getInetAddress().getHostName(), socket.getPort());
130 }
131 SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(
132 socket,
133 socket.getInetAddress().getHostName(),
134 socket.getPort(),
135 true);
136
137 sslSocket.setUseClientMode(false);
138 sslSocket.setNeedClientAuth(needClientCertificate);
139 return sslSocket;
140 }
141 };
142
143 }
144
145 /**
146 * <p>
147 * Indicates whether some other object is "equal to" this one.
148 * </p>
149 *
150 * <p>
151 * Two <code>CacaoRMIServerSocketFactory</code> objects are equal if they
152 * have been constructed with the same SSL socket configuration parameters.
153 * </p>
154 *
155 * <p>
156 * A subclass should override this method (as well as {@link #hashCode()})
157 * if it adds instance state that affects equality.
158 * </p>
159 *
160 * @param obj the reference object with which to compare.
161 *
162 * @return <code>true</code> if this object is the same as the obj
163 * argument <code>false</code> otherwise.
164 */
165 public boolean equals(Object obj)
166 {
167 if (obj == null)
168 return false;
169 if (obj == this)
170 return true;
171 if (!(obj instanceof DirectoryRMIServerSocketFactory))
172 return false;
173 DirectoryRMIServerSocketFactory that =
174 (DirectoryRMIServerSocketFactory) obj;
175 return (getClass().equals(that.getClass()) && checkParameters(that));
176 }
177
178 /**
179 * Checks if inputs parameters are OK.
180 * @param that the input parameter
181 * @return true or false.
182 */
183 private boolean checkParameters(DirectoryRMIServerSocketFactory that)
184 {
185 if (needClientCertificate != that.needClientCertificate)
186 return false;
187
188 if (!sslSocketFactory.equals(that.sslSocketFactory))
189 return false;
190
191 return true;
192 }
193
194 /**
195 * <p>Returns a hash code value for this
196 * <code>CacaoRMIServerSocketFactory</code>.</p>
197 *
198 * @return a hash code value for this
199 * <code>CacaoRMIServerSocketFactory</code>.
200 */
201 public int hashCode()
202 {
203 return getClass().hashCode()
204 + (needClientCertificate ? Boolean.TRUE.hashCode() : Boolean.FALSE
205 .hashCode()) + (sslSocketFactory.hashCode());
206 }
207
208 }