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 }