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. package javax.rmi.ssl;
  11. import java.io.IOException;
  12. import java.net.ServerSocket;
  13. import java.net.Socket;
  14. import java.rmi.server.RMIServerSocketFactory;
  15. import java.util.Arrays;
  16. import java.util.List;
  17. import javax.net.ssl.SSLServerSocketFactory;
  18. import javax.net.ssl.SSLSocket;
  19. import javax.net.ssl.SSLSocketFactory;
  20. /**
  21. * <p>An <code>SslRMIServerSocketFactory</code> instance is used by the RMI
  22. * runtime in order to obtain server sockets for RMI calls via SSL.</p>
  23. *
  24. * <p>This class implements <code>RMIServerSocketFactory</code> over
  25. * the Secure Sockets Layer (SSL) or Transport Layer Security (TLS)
  26. * protocols.</p>
  27. *
  28. * <p>This class creates SSL sockets using the default
  29. * <code>SSLSocketFactory</code> (see {@link
  30. * SSLSocketFactory#getDefault}) or the default
  31. * <code>SSLServerSocketFactory</code> (see {@link
  32. * SSLServerSocketFactory#getDefault}). Therefore, all instances of
  33. * this class share the same keystore, and the same truststore, when
  34. * client authentication is required by the server. This behavior
  35. * can be modified in subclasses by overriding the {@link
  36. * #createServerSocket(int)} method; in that case, {@link
  37. * #equals(Object) equals} and {@link #hashCode() hashCode} may also
  38. * need to be overridden.</p>
  39. *
  40. * @see javax.net.ssl.SSLSocketFactory
  41. * @see javax.net.ssl.SSLServerSocketFactory
  42. * @see javax.rmi.ssl.SslRMIClientSocketFactory
  43. * @since 1.5
  44. */
  45. public class SslRMIServerSocketFactory implements RMIServerSocketFactory {
  46. /**
  47. * <p>Creates a new <code>SslRMIServerSocketFactory</code> with
  48. * the default SSL socket configuration.</p>
  49. *
  50. * <p>SSL connections accepted by server sockets created by this
  51. * factory have the default cipher suites and protocol versions
  52. * enabled and do not require client authentication.</p>
  53. */
  54. public SslRMIServerSocketFactory() {
  55. this(null, null, false);
  56. }
  57. /**
  58. * <p>Creates a new <code>SslRMIServerSocketFactory</code> with
  59. * the specified SSL socket configuration.</p>
  60. *
  61. * @param enabledCipherSuites names of all the cipher suites to
  62. * enable on SSL connections accepted by server sockets created by
  63. * this factory, or <code>null</code> to use the cipher suites
  64. * that are enabled by default
  65. *
  66. * @param enabledProtocols names of all the protocol versions to
  67. * enable on SSL connections accepted by server sockets created by
  68. * this factory, or <code>null</code> to use the protocol versions
  69. * that are enabled by default
  70. *
  71. * @param needClientAuth <code>true</code> to require client
  72. * authentication on SSL connections accepted by server sockets
  73. * created by this factory; <code>false</code> to not require
  74. * client authentication
  75. *
  76. * @exception IllegalArgumentException when one or more of the cipher
  77. * suites named by the <code>enabledCipherSuites</code> parameter is
  78. * not supported, when one or more of the protocols named by the
  79. * <code>enabledProtocols</code> parameter is not supported or when
  80. * a problem is encountered while trying to check if the supplied
  81. * cipher suites and protocols to be enabled are supported.
  82. *
  83. * @see SSLSocket#setEnabledCipherSuites
  84. * @see SSLSocket#setEnabledProtocols
  85. * @see SSLSocket#setNeedClientAuth
  86. */
  87. public SslRMIServerSocketFactory(String[] enabledCipherSuites,
  88. String[] enabledProtocols,
  89. boolean needClientAuth)
  90. throws IllegalArgumentException {
  91. // Initialize the configuration parameters.
  92. //
  93. this.enabledCipherSuites = enabledCipherSuites == null ?
  94. null : (String[]) enabledCipherSuites.clone();
  95. this.enabledProtocols = enabledProtocols == null ?
  96. null : (String[]) enabledProtocols.clone();
  97. this.needClientAuth = needClientAuth;
  98. // Force the initialization of the default at construction time,
  99. // rather than delaying it to the first time createServerSocket()
  100. // is called.
  101. //
  102. final SSLSocketFactory sslSocketFactory = getDefaultSSLSocketFactory();
  103. SSLSocket sslSocket = null;
  104. if (this.enabledCipherSuites != null || this.enabledProtocols != null) {
  105. try {
  106. sslSocket = (SSLSocket) sslSocketFactory.createSocket();
  107. } catch (Exception e) {
  108. final String msg = "Unable to check if the cipher suites " +
  109. "and protocols to enable are supported";
  110. throw (IllegalArgumentException)
  111. new IllegalArgumentException(msg).initCause(e);
  112. }
  113. }
  114. // Check if all the cipher suites and protocol versions to enable
  115. // are supported by the underlying SSL/TLS implementation and if
  116. // true create lists from arrays.
  117. //
  118. if (this.enabledCipherSuites != null) {
  119. sslSocket.setEnabledCipherSuites(this.enabledCipherSuites);
  120. enabledCipherSuitesList =
  121. Arrays.asList((String[]) this.enabledCipherSuites);
  122. }
  123. if (this.enabledProtocols != null) {
  124. sslSocket.setEnabledProtocols(this.enabledProtocols);
  125. enabledProtocolsList =
  126. Arrays.asList((String[]) this.enabledProtocols);
  127. }
  128. }
  129. /**
  130. * <p>Returns the names of the cipher suites enabled on SSL
  131. * connections accepted by server sockets created by this factory,
  132. * or <code>null</code> if this factory uses the cipher suites
  133. * that are enabled by default.</p>
  134. *
  135. * @return an array of cipher suites enabled, or <code>null</code>
  136. *
  137. * @see SSLSocket#setEnabledCipherSuites
  138. */
  139. public final String[] getEnabledCipherSuites() {
  140. return enabledCipherSuites == null ?
  141. null : (String[]) enabledCipherSuites.clone();
  142. }
  143. /**
  144. * <p>Returns the names of the protocol versions enabled on SSL
  145. * connections accepted by server sockets created by this factory,
  146. * or <code>null</code> if this factory uses the protocol versions
  147. * that are enabled by default.</p>
  148. *
  149. * @return an array of protocol versions enabled, or
  150. * <code>null</code>
  151. *
  152. * @see SSLSocket#setEnabledProtocols
  153. */
  154. public final String[] getEnabledProtocols() {
  155. return enabledProtocols == null ?
  156. null : (String[]) enabledProtocols.clone();
  157. }
  158. /**
  159. * <p>Returns <code>true</code> if client authentication is
  160. * required on SSL connections accepted by server sockets created
  161. * by this factory.</p>
  162. *
  163. * @return <code>true</code> if client authentication is required
  164. *
  165. * @see SSLSocket#setNeedClientAuth
  166. */
  167. public final boolean getNeedClientAuth() {
  168. return needClientAuth;
  169. }
  170. /**
  171. * <p>Creates a server socket that accepts SSL connections
  172. * configured according to this factory's SSL socket configuration
  173. * parameters.</p>
  174. */
  175. public ServerSocket createServerSocket(int port) throws IOException {
  176. final SSLSocketFactory sslSocketFactory = getDefaultSSLSocketFactory();
  177. return new ServerSocket(port) {
  178. public Socket accept() throws IOException {
  179. Socket socket = super.accept();
  180. SSLSocket sslSocket = (SSLSocket)
  181. sslSocketFactory.createSocket(
  182. socket, socket.getInetAddress().getHostName(),
  183. socket.getPort(), true);
  184. sslSocket.setUseClientMode(false);
  185. if (enabledCipherSuites != null) {
  186. sslSocket.setEnabledCipherSuites(enabledCipherSuites);
  187. }
  188. if (enabledProtocols != null) {
  189. sslSocket.setEnabledProtocols(enabledProtocols);
  190. }
  191. sslSocket.setNeedClientAuth(needClientAuth);
  192. return sslSocket;
  193. }
  194. };
  195. // If we do not instantiate the server socket class, but
  196. // instead must layer on top of an arbitrary server socket,
  197. // then this implementation would become uglier, like this
  198. // (given "serverSocket" to layer on top of):
  199. //
  200. // return new ForwardingServerSocket(serverSocket) {
  201. // public Socket accept() throws IOException {
  202. // Socket socket = serverSocket.accept();
  203. // SSLSocket sslSocket =
  204. // (SSLSocket) sslSocketFactory.createSocket(
  205. // socket,
  206. // socket.getInetAddress().getHostName(),
  207. // socket.getPort(),
  208. // true);
  209. // sslSocket.setUseClientMode(false);
  210. // if (enabledProtocols != null) {
  211. // sslSocket.setEnabledProtocols(enabledProtocols);
  212. // }
  213. // if (enabledCipherSuites != null) {
  214. // sslSocket.setEnabledCipherSuites(enabledCipherSuites);
  215. // }
  216. // sslSocket.setNeedClientAuth(needClientAuth);
  217. // return sslSocket;
  218. // }
  219. // public ServerSocketChannel getChannel() {
  220. // return null;
  221. // }
  222. // public String toString() {
  223. // return serverSocket.toString();
  224. // }
  225. // };
  226. }
  227. /**
  228. * <p>Indicates whether some other object is "equal to" this one.</p>
  229. *
  230. * <p>Two <code>SslRMIServerSocketFactory</code> objects are equal
  231. * if they have been constructed with the same SSL socket
  232. * configuration parameters.</p>
  233. *
  234. * <p>A subclass should override this method (as well as
  235. * {@link #hashCode()}) if it adds instance state that affects
  236. * equality.</p>
  237. */
  238. public boolean equals(Object obj) {
  239. if (obj == null) return false;
  240. if (obj == this) return true;
  241. if (!(obj instanceof SslRMIServerSocketFactory))
  242. return false;
  243. SslRMIServerSocketFactory that = (SslRMIServerSocketFactory) obj;
  244. return (getClass().equals(that.getClass()) && checkParameters(that));
  245. }
  246. private boolean checkParameters(SslRMIServerSocketFactory that) {
  247. // needClientAuth flag
  248. //
  249. if (needClientAuth != that.needClientAuth)
  250. return false;
  251. // enabledCipherSuites
  252. //
  253. if ((enabledCipherSuites == null && that.enabledCipherSuites != null) ||
  254. (enabledCipherSuites != null && that.enabledCipherSuites == null))
  255. return false;
  256. if (enabledCipherSuites != null && that.enabledCipherSuites != null) {
  257. List thatEnabledCipherSuitesList =
  258. Arrays.asList((String[]) that.enabledCipherSuites);
  259. if (!enabledCipherSuitesList.equals(thatEnabledCipherSuitesList))
  260. return false;
  261. }
  262. // enabledProtocols
  263. //
  264. if ((enabledProtocols == null && that.enabledProtocols != null) ||
  265. (enabledProtocols != null && that.enabledProtocols == null))
  266. return false;
  267. if (enabledProtocols != null && that.enabledProtocols != null) {
  268. List thatEnabledProtocolsList =
  269. Arrays.asList((String[]) that.enabledProtocols);
  270. if (!enabledProtocolsList.equals(thatEnabledProtocolsList))
  271. return false;
  272. }
  273. return true;
  274. }
  275. /**
  276. * <p>Returns a hash code value for this
  277. * <code>SslRMIServerSocketFactory</code>.</p>
  278. *
  279. * @return a hash code value for this
  280. * <code>SslRMIServerSocketFactory</code>.
  281. */
  282. public int hashCode() {
  283. return getClass().hashCode() +
  284. (needClientAuth ? Boolean.TRUE.hashCode() : Boolean.FALSE.hashCode()) +
  285. (enabledCipherSuites == null ? 0 : enabledCipherSuitesList.hashCode()) +
  286. (enabledProtocols == null ? 0 : enabledProtocolsList.hashCode());
  287. }
  288. // We use a static field because:
  289. //
  290. // SSLSocketFactory.getDefault() always returns the same object
  291. // (at least on Sun's implementation), and we want to make sure that
  292. // the Javadoc & the implementation stay in sync.
  293. //
  294. // If someone needs to have different SslRMIServerSocketFactory factories
  295. // with different underlying SSLSocketFactory objects using different
  296. // key and trust stores, he can always do so by subclassing this class and
  297. // overriding createServerSocket(int port).
  298. //
  299. private static SSLSocketFactory defaultSSLSocketFactory = null;
  300. private static synchronized SSLSocketFactory getDefaultSSLSocketFactory() {
  301. if (defaultSSLSocketFactory == null)
  302. defaultSSLSocketFactory =
  303. (SSLSocketFactory) SSLSocketFactory.getDefault();
  304. return defaultSSLSocketFactory;
  305. }
  306. private final String[] enabledCipherSuites;
  307. private final String[] enabledProtocols;
  308. private final boolean needClientAuth;
  309. private List enabledCipherSuitesList;
  310. private List enabledProtocolsList;
  311. // private static class ForwardingServerSocket extends ServerSocket {
  312. // private final ServerSocket ss;
  313. // ForwardingServerSocket(ServerSocket ss) throws IOException {
  314. // super();
  315. // this.ss = ss;
  316. // }
  317. // public void bind(SocketAddress endpoint) throws IOException {
  318. // ss.bind(endpoint);
  319. // }
  320. // public void bind(SocketAddress endpoint, int backlog)
  321. // throws IOException
  322. // {
  323. // ss.bind(endpoint, backlog);
  324. // }
  325. // public InetAddress getInetAddress() {
  326. // return ss.getInetAddress();
  327. // }
  328. // public int getLocalPort() {
  329. // return ss.getLocalPort();
  330. // }
  331. // public SocketAddress getLocalSocketAddress() {
  332. // return ss.getLocalSocketAddress();
  333. // }
  334. // public Socket accept() throws IOException {
  335. // return ss.accept();
  336. // }
  337. // public void close() throws IOException {
  338. // ss.close();
  339. // }
  340. // public ServerSocketChannel getChannel() {
  341. // return ss.getChannel();
  342. // }
  343. // public boolean isBound() {
  344. // return ss.isBound();
  345. // }
  346. // public boolean isClosed() {
  347. // return ss.isClosed();
  348. // }
  349. // public void setSoTimeout(int timeout) throws SocketException {
  350. // ss.setSoTimeout(timeout);
  351. // }
  352. // public int getSoTimeout() throws IOException {
  353. // return ss.getSoTimeout();
  354. // }
  355. // public void setReuseAddress(boolean on) throws SocketException {
  356. // ss.setReuseAddress(on);
  357. // }
  358. // public boolean getReuseAddress() throws SocketException {
  359. // return ss.getReuseAddress();
  360. // }
  361. // public String toString() {
  362. // return ss.toString();
  363. // }
  364. // public void setReceiveBufferSize(int size) throws SocketException {
  365. // ss.setReceiveBufferSize(size);
  366. // }
  367. // public int getReceiveBufferSize() throws SocketException {
  368. // return ss.getReceiveBufferSize();
  369. // }
  370. // }
  371. }