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 2008 Sun Microsystems, Inc.
026 */
027
028 package org.opends.admin.ads.util;
029
030 import java.io.IOException;
031 import java.net.Socket;
032 import java.net.InetAddress;
033 import java.util.Map;
034 import java.util.HashMap;
035
036 import java.security.GeneralSecurityException;
037
038 import javax.net.SocketFactory;
039 import javax.net.ssl.KeyManager;
040 import javax.net.ssl.SSLContext;
041 import javax.net.ssl.SSLSocketFactory;
042 import javax.net.ssl.SSLKeyException;
043 import javax.net.ssl.TrustManager;
044
045 /**
046 * An implementation of SSLSocketFactory.
047 */
048 public class TrustedSocketFactory extends SSLSocketFactory
049 {
050 private static Map<Thread, TrustManager> hmTrustManager =
051 new HashMap<Thread, TrustManager>();
052 private static Map<Thread, KeyManager> hmKeyManager =
053 new HashMap<Thread, KeyManager>();
054
055 private static Map<TrustManager, SocketFactory> hmDefaultFactoryTm =
056 new HashMap<TrustManager, SocketFactory>();
057 private static Map<KeyManager, SocketFactory> hmDefaultFactoryKm =
058 new HashMap<KeyManager, SocketFactory>();
059
060 private SSLSocketFactory innerFactory;
061 private TrustManager trustManager;
062 private KeyManager keyManager;
063
064 /**
065 * Constructor of the TrustedSocketFactory.
066 * @param trustManager the trust manager to use.
067 * @param keyManager the key manager to use.
068 */
069 public TrustedSocketFactory(TrustManager trustManager, KeyManager keyManager)
070 {
071 this.trustManager = trustManager;
072 this.keyManager = keyManager;
073 }
074
075 /**
076 * Sets the provided trust and key manager for the operations in the
077 * current thread.
078 *
079 * @param trustManager
080 * the trust manager to use.
081 * @param keyManager
082 * the key manager to use.
083 */
084 public static synchronized void setCurrentThreadTrustManager(
085 TrustManager trustManager, KeyManager keyManager)
086 {
087 setThreadTrustManager(trustManager, Thread.currentThread());
088 setThreadKeyManager (keyManager, Thread.currentThread());
089 }
090
091 /**
092 * Sets the provided trust manager for the operations in the provided thread.
093 * @param trustManager the trust manager to use.
094 * @param thread the thread where we want to use the provided trust manager.
095 */
096 public static synchronized void setThreadTrustManager(
097 TrustManager trustManager, Thread thread)
098 {
099 TrustManager currentTrustManager = hmTrustManager.get(thread);
100 if (currentTrustManager != null) {
101 hmDefaultFactoryTm.remove(currentTrustManager);
102 hmTrustManager.remove(thread);
103 }
104 if (trustManager != null) {
105 hmTrustManager.put(thread, trustManager);
106 }
107 }
108
109 /**
110 * Sets the provided key manager for the operations in the provided thread.
111 * @param keyManager the key manager to use.
112 * @param thread the thread where we want to use the provided key manager.
113 */
114 public static synchronized void setThreadKeyManager(
115 KeyManager keyManager, Thread thread)
116 {
117 KeyManager currentKeyManager = hmKeyManager.get(thread);
118 if (currentKeyManager != null) {
119 hmDefaultFactoryKm.remove(currentKeyManager);
120 hmKeyManager.remove(thread);
121 }
122 if (keyManager != null) {
123 hmKeyManager.put(thread, keyManager);
124 }
125 }
126
127 //
128 // SocketFactory implementation
129 //
130 /**
131 * Returns the default SSL socket factory. The default
132 * implementation can be changed by setting the value of the
133 * "ssl.SocketFactory.provider" security property (in the Java
134 * security properties file) to the desired class. If SSL has not
135 * been configured properly for this virtual machine, the factory
136 * will be inoperative (reporting instantiation exceptions).
137 *
138 * @return the default SocketFactory
139 */
140 public static synchronized SocketFactory getDefault()
141 {
142 Thread currentThread = Thread.currentThread();
143 TrustManager trustManager = hmTrustManager.get(currentThread);
144 KeyManager keyManager = hmKeyManager.get(currentThread);
145 SocketFactory result;
146
147 if (trustManager == null)
148 {
149 if (keyManager == null)
150 {
151 result = new TrustedSocketFactory(null,null);
152 }
153 else
154 {
155 result = hmDefaultFactoryKm.get(keyManager);
156 if (result == null)
157 {
158 result = new TrustedSocketFactory(null,keyManager);
159 hmDefaultFactoryKm.put(keyManager, result);
160 }
161 }
162 }
163 else
164 {
165 if (keyManager == null)
166 {
167 result = hmDefaultFactoryTm.get(trustManager);
168 if (result == null)
169 {
170 result = new TrustedSocketFactory(trustManager, null);
171 hmDefaultFactoryTm.put(trustManager, result);
172 }
173 }
174 else
175 {
176 SocketFactory tmsf = hmDefaultFactoryTm.get(trustManager);
177 SocketFactory kmsf = hmDefaultFactoryKm.get(keyManager);
178 if ( tmsf == null || kmsf == null)
179 {
180 result = new TrustedSocketFactory(trustManager, keyManager);
181 hmDefaultFactoryTm.put(trustManager, result);
182 hmDefaultFactoryKm.put(keyManager, result);
183 }
184 else
185 if ( !tmsf.equals(kmsf) )
186 {
187 result = new TrustedSocketFactory(trustManager, keyManager);
188 hmDefaultFactoryTm.put(trustManager, result);
189 hmDefaultFactoryKm.put(keyManager, result);
190 }
191 else
192 {
193 result = tmsf ;
194 }
195 }
196 }
197
198 return result;
199 }
200
201 /**
202 * {@inheritDoc}
203 */
204 public Socket createSocket(InetAddress address, int port) throws IOException {
205 return getInnerFactory().createSocket(address, port);
206 }
207
208 /**
209 * {@inheritDoc}
210 */
211 public Socket createSocket(InetAddress address, int port,
212 InetAddress clientAddress, int clientPort) throws IOException
213 {
214 return getInnerFactory().createSocket(address, port, clientAddress,
215 clientPort);
216 }
217
218 /**
219 * {@inheritDoc}
220 */
221 public Socket createSocket(String host, int port) throws IOException
222 {
223 return getInnerFactory().createSocket(host, port);
224 }
225
226 /**
227 * {@inheritDoc}
228 */
229 public Socket createSocket(String host, int port, InetAddress clientHost,
230 int clientPort) throws IOException
231 {
232 return getInnerFactory().createSocket(host, port, clientHost, clientPort);
233 }
234
235 /**
236 * {@inheritDoc}
237 */
238 public Socket createSocket(Socket s, String host, int port, boolean autoClose)
239 throws IOException
240 {
241 return getInnerFactory().createSocket(s, host, port, autoClose);
242 }
243
244 /**
245 * {@inheritDoc}
246 */
247 public String[] getDefaultCipherSuites()
248 {
249 try
250 {
251 return getInnerFactory().getDefaultCipherSuites();
252 }
253 catch(IOException x)
254 {
255 return new String[0];
256 }
257 }
258
259 /**
260 * {@inheritDoc}
261 */
262 public String[] getSupportedCipherSuites()
263 {
264 try
265 {
266 return getInnerFactory().getSupportedCipherSuites();
267 }
268 catch(IOException x)
269 {
270 return new String[0];
271 }
272 }
273
274
275 //
276 // Private
277 //
278
279 private SSLSocketFactory getInnerFactory() throws IOException {
280 if (innerFactory == null)
281 {
282 String algorithm = "TLSv1";
283 SSLKeyException xx;
284 KeyManager[] km = null;
285 TrustManager[] tm = null;
286
287 try {
288 SSLContext sslCtx = SSLContext.getInstance(algorithm);
289 if (trustManager != null)
290 {
291 tm = new TrustManager[] { trustManager };
292 }
293 if (keyManager != null)
294 {
295 km = new KeyManager[] { keyManager };
296 }
297 sslCtx.init(km, tm, new java.security.SecureRandom() );
298 innerFactory = sslCtx.getSocketFactory();
299 }
300 catch(GeneralSecurityException x) {
301 xx = new SSLKeyException("Failed to create SSLContext for " +
302 algorithm);
303 xx.initCause(x);
304 throw xx;
305 }
306 }
307 return innerFactory;
308 }
309 }
310