KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > rmi > ssl > SslRMIServerSocketFactory


1 /*
2  * @(#)file SslRMIServerSocketFactory.java
3  * @(#)author Sun Microsystems, Inc.
4  * @(#)version 1.16
5  * @(#)date 04/06/01
6  *
7  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
8  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
9  */

10
11 package javax.rmi.ssl;
12
13 import java.io.IOException JavaDoc;
14 import java.net.ServerSocket JavaDoc;
15 import java.net.Socket JavaDoc;
16 import java.rmi.server.RMIServerSocketFactory JavaDoc;
17 import java.util.Arrays JavaDoc;
18 import java.util.List JavaDoc;
19 import javax.net.ssl.SSLServerSocketFactory;
20 import javax.net.ssl.SSLSocket;
21 import javax.net.ssl.SSLSocketFactory;
22
23 /**
24  * <p>An <code>SslRMIServerSocketFactory</code> instance is used by the RMI
25  * runtime in order to obtain server sockets for RMI calls via SSL.</p>
26  *
27  * <p>This class implements <code>RMIServerSocketFactory</code> over
28  * the Secure Sockets Layer (SSL) or Transport Layer Security (TLS)
29  * protocols.</p>
30  *
31  * <p>This class creates SSL sockets using the default
32  * <code>SSLSocketFactory</code> (see {@link
33  * SSLSocketFactory#getDefault}) or the default
34  * <code>SSLServerSocketFactory</code> (see {@link
35  * SSLServerSocketFactory#getDefault}). Therefore, all instances of
36  * this class share the same keystore, and the same truststore, when
37  * client authentication is required by the server. This behavior
38  * can be modified in subclasses by overriding the {@link
39  * #createServerSocket(int)} method; in that case, {@link
40  * #equals(Object) equals} and {@link #hashCode() hashCode} may also
41  * need to be overridden.</p>
42  *
43  * @see javax.net.ssl.SSLSocketFactory
44  * @see javax.net.ssl.SSLServerSocketFactory
45  * @see javax.rmi.ssl.SslRMIClientSocketFactory
46  * @since 1.5
47  */

48 public class SslRMIServerSocketFactory implements RMIServerSocketFactory JavaDoc {
49
50     /**
51      * <p>Creates a new <code>SslRMIServerSocketFactory</code> with
52      * the default SSL socket configuration.</p>
53      *
54      * <p>SSL connections accepted by server sockets created by this
55      * factory have the default cipher suites and protocol versions
56      * enabled and do not require client authentication.</p>
57      */

58     public SslRMIServerSocketFactory() {
59         this(null, null, false);
60     }
61
62     /**
63      * <p>Creates a new <code>SslRMIServerSocketFactory</code> with
64      * the specified SSL socket configuration.</p>
65      *
66      * @param enabledCipherSuites names of all the cipher suites to
67      * enable on SSL connections accepted by server sockets created by
68      * this factory, or <code>null</code> to use the cipher suites
69      * that are enabled by default
70      *
71      * @param enabledProtocols names of all the protocol versions to
72      * enable on SSL connections accepted by server sockets created by
73      * this factory, or <code>null</code> to use the protocol versions
74      * that are enabled by default
75      *
76      * @param needClientAuth <code>true</code> to require client
77      * authentication on SSL connections accepted by server sockets
78      * created by this factory; <code>false</code> to not require
79      * client authentication
80      *
81      * @exception IllegalArgumentException when one or more of the cipher
82      * suites named by the <code>enabledCipherSuites</code> parameter is
83      * not supported, when one or more of the protocols named by the
84      * <code>enabledProtocols</code> parameter is not supported or when
85      * a problem is encountered while trying to check if the supplied
86      * cipher suites and protocols to be enabled are supported.
87      *
88      * @see SSLSocket#setEnabledCipherSuites
89      * @see SSLSocket#setEnabledProtocols
90      * @see SSLSocket#setNeedClientAuth
91      */

92     public SslRMIServerSocketFactory(String JavaDoc[] enabledCipherSuites,
93                                      String JavaDoc[] enabledProtocols,
94                                      boolean needClientAuth)
95     throws IllegalArgumentException JavaDoc {
96
97         // Initialize the configuration parameters.
98
//
99
this.enabledCipherSuites = enabledCipherSuites == null ?
100         null : (String JavaDoc[]) enabledCipherSuites.clone();
101         this.enabledProtocols = enabledProtocols == null ?
102         null : (String JavaDoc[]) enabledProtocols.clone();
103         this.needClientAuth = needClientAuth;
104
105         // Force the initialization of the default at construction time,
106
// rather than delaying it to the first time createServerSocket()
107
// is called.
108
//
109
final SSLSocketFactory sslSocketFactory = getDefaultSSLSocketFactory();
110     SSLSocket sslSocket = null;
111         if (this.enabledCipherSuites != null || this.enabledProtocols != null) {
112         try {
113         sslSocket = (SSLSocket) sslSocketFactory.createSocket();
114         } catch (Exception JavaDoc e) {
115         final String JavaDoc msg = "Unable to check if the cipher suites " +
116             "and protocols to enable are supported";
117         throw (IllegalArgumentException JavaDoc)
118             new IllegalArgumentException JavaDoc(msg).initCause(e);
119         }
120     }
121
122     // Check if all the cipher suites and protocol versions to enable
123
// are supported by the underlying SSL/TLS implementation and if
124
// true create lists from arrays.
125
//
126
if (this.enabledCipherSuites != null) {
127         sslSocket.setEnabledCipherSuites(this.enabledCipherSuites);
128             enabledCipherSuitesList =
129                 Arrays.asList((String JavaDoc[]) this.enabledCipherSuites);
130     }
131         if (this.enabledProtocols != null) {
132         sslSocket.setEnabledProtocols(this.enabledProtocols);
133             enabledProtocolsList =
134                 Arrays.asList((String JavaDoc[]) this.enabledProtocols);
135     }
136     }
137
138     /**
139      * <p>Returns the names of the cipher suites enabled on SSL
140      * connections accepted by server sockets created by this factory,
141      * or <code>null</code> if this factory uses the cipher suites
142      * that are enabled by default.</p>
143      *
144      * @return an array of cipher suites enabled, or <code>null</code>
145      *
146      * @see SSLSocket#setEnabledCipherSuites
147      */

148     public final String JavaDoc[] getEnabledCipherSuites() {
149         return enabledCipherSuites == null ?
150     null : (String JavaDoc[]) enabledCipherSuites.clone();
151     }
152
153     /**
154      * <p>Returns the names of the protocol versions enabled on SSL
155      * connections accepted by server sockets created by this factory,
156      * or <code>null</code> if this factory uses the protocol versions
157      * that are enabled by default.</p>
158      *
159      * @return an array of protocol versions enabled, or
160      * <code>null</code>
161      *
162      * @see SSLSocket#setEnabledProtocols
163      */

164     public final String JavaDoc[] getEnabledProtocols() {
165         return enabledProtocols == null ?
166     null : (String JavaDoc[]) enabledProtocols.clone();
167     }
168
169     /**
170      * <p>Returns <code>true</code> if client authentication is
171      * required on SSL connections accepted by server sockets created
172      * by this factory.</p>
173      *
174      * @return <code>true</code> if client authentication is required
175      *
176      * @see SSLSocket#setNeedClientAuth
177      */

178     public final boolean getNeedClientAuth() {
179         return needClientAuth;
180     }
181
182     /**
183      * <p>Creates a server socket that accepts SSL connections
184      * configured according to this factory's SSL socket configuration
185      * parameters.</p>
186      */

187     public ServerSocket JavaDoc createServerSocket(int port) throws IOException JavaDoc {
188         final SSLSocketFactory sslSocketFactory = getDefaultSSLSocketFactory();
189         return new ServerSocket JavaDoc(port) {
190             public Socket JavaDoc accept() throws IOException JavaDoc {
191                 Socket JavaDoc socket = super.accept();
192                 SSLSocket sslSocket = (SSLSocket)
193                     sslSocketFactory.createSocket(
194                         socket, socket.getInetAddress().getHostName(),
195                         socket.getPort(), true);
196                 sslSocket.setUseClientMode(false);
197                 if (enabledCipherSuites != null) {
198                     sslSocket.setEnabledCipherSuites(enabledCipherSuites);
199                 }
200                 if (enabledProtocols != null) {
201                     sslSocket.setEnabledProtocols(enabledProtocols);
202                 }
203                 sslSocket.setNeedClientAuth(needClientAuth);
204                 return sslSocket;
205             }
206         };
207
208         // If we do not instantiate the server socket class, but
209
// instead must layer on top of an arbitrary server socket,
210
// then this implementation would become uglier, like this
211
// (given "serverSocket" to layer on top of):
212
//
213
// return new ForwardingServerSocket(serverSocket) {
214
// public Socket accept() throws IOException {
215
// Socket socket = serverSocket.accept();
216
// SSLSocket sslSocket =
217
// (SSLSocket) sslSocketFactory.createSocket(
218
// socket,
219
// socket.getInetAddress().getHostName(),
220
// socket.getPort(),
221
// true);
222
// sslSocket.setUseClientMode(false);
223
// if (enabledProtocols != null) {
224
// sslSocket.setEnabledProtocols(enabledProtocols);
225
// }
226
// if (enabledCipherSuites != null) {
227
// sslSocket.setEnabledCipherSuites(enabledCipherSuites);
228
// }
229
// sslSocket.setNeedClientAuth(needClientAuth);
230
// return sslSocket;
231
// }
232
// public ServerSocketChannel getChannel() {
233
// return null;
234
// }
235
// public String toString() {
236
// return serverSocket.toString();
237
// }
238
// };
239
}
240
241     /**
242      * <p>Indicates whether some other object is "equal to" this one.</p>
243      *
244      * <p>Two <code>SslRMIServerSocketFactory</code> objects are equal
245      * if they have been constructed with the same SSL socket
246      * configuration parameters.</p>
247      *
248      * <p>A subclass should override this method (as well as
249      * {@link #hashCode()}) if it adds instance state that affects
250      * equality.</p>
251      */

252     public boolean equals(Object JavaDoc obj) {
253         if (obj == null) return false;
254         if (obj == this) return true;
255         if (!(obj instanceof SslRMIServerSocketFactory JavaDoc))
256             return false;
257         SslRMIServerSocketFactory JavaDoc that = (SslRMIServerSocketFactory JavaDoc) obj;
258         return (getClass().equals(that.getClass()) && checkParameters(that));
259     }
260
261     private boolean checkParameters(SslRMIServerSocketFactory JavaDoc that) {
262         // needClientAuth flag
263
//
264
if (needClientAuth != that.needClientAuth)
265             return false;
266
267         // enabledCipherSuites
268
//
269
if ((enabledCipherSuites == null && that.enabledCipherSuites != null) ||
270             (enabledCipherSuites != null && that.enabledCipherSuites == null))
271             return false;
272         if (enabledCipherSuites != null && that.enabledCipherSuites != null) {
273             List JavaDoc thatEnabledCipherSuitesList =
274                 Arrays.asList((String JavaDoc[]) that.enabledCipherSuites);
275             if (!enabledCipherSuitesList.equals(thatEnabledCipherSuitesList))
276                 return false;
277         }
278
279         // enabledProtocols
280
//
281
if ((enabledProtocols == null && that.enabledProtocols != null) ||
282             (enabledProtocols != null && that.enabledProtocols == null))
283             return false;
284         if (enabledProtocols != null && that.enabledProtocols != null) {
285             List JavaDoc thatEnabledProtocolsList =
286                 Arrays.asList((String JavaDoc[]) that.enabledProtocols);
287             if (!enabledProtocolsList.equals(thatEnabledProtocolsList))
288                 return false;
289         }
290
291         return true;
292     }
293
294     /**
295      * <p>Returns a hash code value for this
296      * <code>SslRMIServerSocketFactory</code>.</p>
297      *
298      * @return a hash code value for this
299      * <code>SslRMIServerSocketFactory</code>.
300      */

301     public int hashCode() {
302         return getClass().hashCode() +
303         (needClientAuth ? Boolean.TRUE.hashCode() : Boolean.FALSE.hashCode()) +
304         (enabledCipherSuites == null ? 0 : enabledCipherSuitesList.hashCode()) +
305         (enabledProtocols == null ? 0 : enabledProtocolsList.hashCode());
306     }
307
308     // We use a static field because:
309
//
310
// SSLSocketFactory.getDefault() always returns the same object
311
// (at least on Sun's implementation), and we want to make sure that
312
// the Javadoc & the implementation stay in sync.
313
//
314
// If someone needs to have different SslRMIServerSocketFactory factories
315
// with different underlying SSLSocketFactory objects using different
316
// key and trust stores, he can always do so by subclassing this class and
317
// overriding createServerSocket(int port).
318
//
319
private static SSLSocketFactory defaultSSLSocketFactory = null;
320
321     private static synchronized SSLSocketFactory getDefaultSSLSocketFactory() {
322         if (defaultSSLSocketFactory == null)
323             defaultSSLSocketFactory =
324                 (SSLSocketFactory) SSLSocketFactory.getDefault();
325         return defaultSSLSocketFactory;
326     }
327
328     private final String JavaDoc[] enabledCipherSuites;
329     private final String JavaDoc[] enabledProtocols;
330     private final boolean needClientAuth;
331     private List JavaDoc enabledCipherSuitesList;
332     private List JavaDoc enabledProtocolsList;
333
334 // private static class ForwardingServerSocket extends ServerSocket {
335
// private final ServerSocket ss;
336
// ForwardingServerSocket(ServerSocket ss) throws IOException {
337
// super();
338
// this.ss = ss;
339
// }
340
// public void bind(SocketAddress endpoint) throws IOException {
341
// ss.bind(endpoint);
342
// }
343
// public void bind(SocketAddress endpoint, int backlog)
344
// throws IOException
345
// {
346
// ss.bind(endpoint, backlog);
347
// }
348
// public InetAddress getInetAddress() {
349
// return ss.getInetAddress();
350
// }
351
// public int getLocalPort() {
352
// return ss.getLocalPort();
353
// }
354
// public SocketAddress getLocalSocketAddress() {
355
// return ss.getLocalSocketAddress();
356
// }
357
// public Socket accept() throws IOException {
358
// return ss.accept();
359
// }
360
// public void close() throws IOException {
361
// ss.close();
362
// }
363
// public ServerSocketChannel getChannel() {
364
// return ss.getChannel();
365
// }
366
// public boolean isBound() {
367
// return ss.isBound();
368
// }
369
// public boolean isClosed() {
370
// return ss.isClosed();
371
// }
372
// public void setSoTimeout(int timeout) throws SocketException {
373
// ss.setSoTimeout(timeout);
374
// }
375
// public int getSoTimeout() throws IOException {
376
// return ss.getSoTimeout();
377
// }
378
// public void setReuseAddress(boolean on) throws SocketException {
379
// ss.setReuseAddress(on);
380
// }
381
// public boolean getReuseAddress() throws SocketException {
382
// return ss.getReuseAddress();
383
// }
384
// public String toString() {
385
// return ss.toString();
386
// }
387
// public void setReceiveBufferSize(int size) throws SocketException {
388
// ss.setReceiveBufferSize(size);
389
// }
390
// public int getReceiveBufferSize() throws SocketException {
391
// return ss.getReceiveBufferSize();
392
// }
393
// }
394
}
395
Popular Tags