KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jmeter > util > JsseSSLManager


1 // $Header: /home/cvs/jakarta-jmeter/src/core/org/apache/jmeter/util/JsseSSLManager.java,v 1.12 2004/02/13 02:21:37 sebb Exp $
2
/*
3  * Copyright 2002-2004 The Apache Software Foundation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17 */

18
19 package org.apache.jmeter.util;
20 import java.net.HttpURLConnection;
21 import java.net.Socket;
22 import java.security.KeyStore;
23 import java.security.Principal;
24 import java.security.PrivateKey;
25 import java.security.Provider;
26 import java.security.SecureRandom;
27 import java.security.cert.CertificateException;
28 import java.security.cert.X509Certificate;
29
30 import org.apache.jmeter.util.keystore.JmeterKeyStore;
31 import org.apache.jorphan.logging.LoggingManager;
32 import org.apache.log.Logger;
33
34 import com.sun.net.ssl.HostnameVerifier;
35 import com.sun.net.ssl.HttpsURLConnection;
36 import com.sun.net.ssl.KeyManager;
37 import com.sun.net.ssl.KeyManagerFactory;
38 import com.sun.net.ssl.SSLContext;
39 import com.sun.net.ssl.TrustManager;
40 import com.sun.net.ssl.X509KeyManager;
41 import com.sun.net.ssl.X509TrustManager;
42
43 /**
44  * The SSLManager handles the KeyStore information for JMeter. Basically, it
45  * handles all the logic for loading and initializing all the JSSE parameters
46  * and selecting the alias to authenticate against if it is available.
47  * SSLManager will try to automatically select the client certificate for you,
48  * but if it can't make a decision, it will pop open a dialog asking you for
49  * more information.
50  *
51  *@author <a HREF="bloritsch@apache.org">Berin Loritsch</a>
52  *Created March 21, 2002
53  *@version $Revision: 1.12 $ $Date: 2004/02/13 02:21:37 $
54  */

55 public class JsseSSLManager extends SSLManager
56 {
57     transient private static Logger log = LoggingManager.getLoggerForClass();
58
59     /**
60      * Cache the SecureRandom instance because it takes a long time to create
61      */

62     private SecureRandom rand;
63     /**
64      * Cache the Context so we can retrieve it from other places
65      */

66     private SSLContext context = null;
67     private Provider pro = null;
68     /**
69      * Private Constructor to remove the possibility of directly instantiating
70      * this object. Create the SSLContext, and wrap all the X509KeyManagers
71      * with our X509KeyManager so that we can choose our alias.
72      *
73      * @param provider Description of Parameter
74      */

75     public JsseSSLManager(Provider provider)
76     {
77         log.debug("ssl Provider = " + provider);
78         setProvider(provider);
79         try
80         {
81             Class iaikProvider =
82                 SSLManager.class.getClassLoader().loadClass(
83                     "iaik.security.jsse.provider.IAIKJSSEProvider");
84             setProvider((Provider) iaikProvider.newInstance());
85         }
86         catch (Exception e)
87         {}
88         if (null == this.rand)
89         {
90             this.rand = new SecureRandom();
91         }
92
93         if ("all"
94             .equalsIgnoreCase(
95                 JMeterUtils.getPropDefault("javax.net.debug", "none")))
96         {
97             System.setProperty("javax.net.debug", "all");
98         }
99         this.getContext();
100         log.info("JsseSSLManager installed");
101     }
102
103     /**
104      * Sets the Context attribute of the JsseSSLManager object
105      *
106      *@param conn The new Context value
107      */

108     public void setContext(HttpURLConnection conn)
109     {
110         if(conn instanceof com.sun.net.ssl.HttpsURLConnection)
111         {
112             com.sun.net.ssl.HttpsURLConnection secureConn =
113                 (com.sun.net.ssl.HttpsURLConnection) conn;
114             secureConn.setSSLSocketFactory(
115                 this.getContext().getSocketFactory());
116         }
117         else if (
118             conn instanceof sun.net.www.protocol.https.HttpsURLConnectionImpl)
119         {
120             sun.net.www.protocol.https.HttpsURLConnectionImpl secureConn =
121                 (sun.net.www.protocol.https.HttpsURLConnectionImpl) conn;
122             secureConn.setSSLSocketFactory(
123                 this.getContext().getSocketFactory());
124         }
125     }
126     
127     /**
128      * Sets the Provider attribute of the JsseSSLManager object
129      *
130      * @param p The new Provider value
131      */

132     protected final void setProvider(Provider p)
133     {
134         super.setProvider(p);
135         if (null == this.pro)
136         {
137             this.pro = p;
138         }
139     }
140     
141     /**
142      * Returns the SSLContext we are using. It is useful for obtaining the
143      * SSLSocketFactory so that your created sockets are authenticated.
144      *
145      * @return The Context value
146      */

147     private SSLContext getContext()
148     {
149         if (null == this.context)
150         {
151             try
152             {
153                 if (pro != null)
154                 {
155                     this.context = SSLContext.getInstance("TLS",pro);
156                 }
157                 else
158                 {
159                     this.context = SSLContext.getInstance("TLS");
160                 }
161                 log.debug("SSL context = " + context);
162             }
163             catch (Exception ee)
164             {
165                 log.error("Exception occurred",ee);
166             }
167             try
168             {
169                 KeyManagerFactory managerFactory =
170                     KeyManagerFactory.getInstance("SunX509");
171                 JmeterKeyStore keys = this.getKeyStore();
172                 managerFactory.init(null, this.defaultpw.toCharArray());
173                 KeyManager[] managers = managerFactory.getKeyManagers();
174                 log.info(keys.getClass().toString());
175                 for (int i = 0; i < managers.length; i++)
176                 {
177                     if (managers[i] instanceof X509KeyManager)
178                     {
179                         X509KeyManager manager = (X509KeyManager) managers[i];
180                         managers[i] = new WrappedX509KeyManager(manager, keys);
181                     }
182                 }
183                 TrustManager[] trusts =
184                     new TrustManager[] {
185                          new AlwaysTrustManager(this.getTrustStore())};
186                 context.init(managers, trusts, this.rand);
187                 HttpsURLConnection.setDefaultSSLSocketFactory(
188                     context.getSocketFactory());
189                 HttpsURLConnection
190                     .setDefaultHostnameVerifier(new HostnameVerifier()
191                 {
192                     public boolean verify(
193                         String urlHostname,
194                         String certHostname)
195                     {
196                         return true;
197                     }
198                 });
199                 log.debug("SSL stuff all set");
200             }
201             catch (Exception e)
202             {
203                 log.error("Exception occurred",e);
204             }
205
206             String[] dCiphers =
207                 this.context.getSocketFactory().getDefaultCipherSuites();
208             String[] sCiphers =
209                 this.context.getSocketFactory().getSupportedCipherSuites();
210             int len =
211                 (dCiphers.length > sCiphers.length)
212                     ? dCiphers.length
213                     : sCiphers.length;
214             for (int i = 0; i < len; i++)
215             {
216                 if (i < dCiphers.length)
217                 {
218                     log.info("Default Cipher: " + dCiphers[i]);
219                 }
220                 if (i < sCiphers.length)
221                 {
222                     log.info("Supported Cipher: " + sCiphers[i]);
223                 }
224             }
225         }
226         return this.context;
227     }
228
229     /**
230      * @author MStover
231      * Created March 21, 2002
232      */

233     protected static class AlwaysTrustManager implements X509TrustManager
234     {
235         /**
236          * Description of the Field
237          */

238         protected X509Certificate[] certs;
239         /**
240          * Constructor for the AlwaysTrustManager object
241          *
242          *@param store Description of Parameter
243          */

244         public AlwaysTrustManager(KeyStore store)
245         {
246             try
247             {
248                 java.util.Enumeration enum = store.aliases();
249                 java.util.ArrayList list =
250                     new java.util.ArrayList(store.size());
251                 while (enum.hasMoreElements())
252                 {
253                     String alias = (String) enum.nextElement();
254                     log.info("AlwaysTrustManager alias: " + alias);
255                     if (store.isCertificateEntry(alias))
256                     {
257                         list.add(store.getCertificate(alias));
258                         log.info(" INSTALLED");
259                     }
260                     else
261                     {
262                         log.info(" SKIPPED");
263                     }
264                 }
265                 this.certs =
266                     (X509Certificate[]) list.toArray(new X509Certificate[] {
267                 });
268             }
269             catch (Exception e)
270             {
271                 this.certs = null;
272             }
273         }
274
275         /**
276          * Gets the AcceptedIssuers attribute of the AlwaysTrustManager object
277          *
278          *@return The AcceptedIssuers value
279          */

280         public X509Certificate[] getAcceptedIssuers()
281         {
282             log.info("Get accepted Issuers");
283             return certs;
284         }
285         /* (non-Javadoc)
286          * @see X509TrustManager#checkClientTrusted(X509Certificate[], String)
287          */

288         public void checkClientTrusted(X509Certificate[] arg0, String arg1)
289             throws CertificateException
290         {}
291
292         /* (non-Javadoc)
293          * @see X509TrustManager#checkServerTrusted(X509Certificate[], String)
294          */

295         public void checkServerTrusted(X509Certificate[] arg0, String arg1)
296             throws CertificateException
297         {}
298
299         public boolean isClientTrusted(X509Certificate[] arg0)
300         {
301             // TODO Auto-generated method stub
302
return true;
303         }
304
305         public boolean isServerTrusted(X509Certificate[] arg0)
306         {
307             // TODO Auto-generated method stub
308
return true;
309         }
310
311     }
312     /**
313      * This is the X509KeyManager we have defined for the sole purpose of
314      * selecting the proper key and certificate based on the keystore available.
315      *
316      * @author MStover
317      * Created March 21, 2002
318      */

319     private static class WrappedX509KeyManager implements X509KeyManager
320     {
321         /**
322          * The parent X509KeyManager
323          */

324         private final X509KeyManager manager;
325         /**
326          * The KeyStore this KeyManager uses
327          */

328         private final JmeterKeyStore store;
329         /**
330          * Instantiate a new WrappedX509KeyManager.
331          *
332          *@param parent The parent X509KeyManager
333          *@param ks The KeyStore we derive our client certs and keys from
334          */

335         public WrappedX509KeyManager(X509KeyManager parent, JmeterKeyStore ks)
336         {
337             this.manager = parent;
338             this.store = ks;
339         }
340         /**
341          * Compiles the list of all client aliases with a private key.
342          * Currently, keyType and issuers are both ignored.
343          *
344          *@param keyType the type of private key the server expects (RSA,
345          * DSA, etc.)
346          *@param issuers the CA certificates we are narrowing our selection
347          * on.
348          *@return the ClientAliases value
349          */

350         public String[] getClientAliases(String keyType, Principal[] issuers)
351         {
352             log.info("WrappedX509Manager: getClientAliases: ");
353             log.info(this.store.getAlias());
354             return new String[] { this.store.getAlias()};
355         }
356         /**
357          * Get the list of server aliases for the SSLServerSockets. This is not
358          * used in JMeter.
359          *
360          * @param keyType the type of private key the server expects (RSA,
361          * DSA, etc.)
362          * @param issuers the CA certificates we are narrowing our selection
363          * on.
364          * @return the ServerAliases value
365          */

366         public String[] getServerAliases(String keyType, Principal[] issuers)
367         {
368             log.info("WrappedX509Manager: getServerAliases: ");
369             log.info(
370                 this.manager.getServerAliases(keyType, issuers).toString());
371             return this.manager.getServerAliases(keyType, issuers);
372         }
373
374         /**
375          * Get the Certificate chain for a particular alias
376          *
377          *@param alias The client alias
378          *@return The CertificateChain value
379          */

380         public X509Certificate[] getCertificateChain(String alias)
381         {
382             log.info("WrappedX509Manager: getCertificateChain(" + alias + ")");
383             log.info(this.store.getCertificateChain().toString());
384             return this.store.getCertificateChain();
385         }
386
387         /**
388          * Get the Private Key for a particular alias
389          *
390          *@param alias The client alias
391          *@return The PrivateKey value
392          */

393         public PrivateKey getPrivateKey(String alias)
394         {
395             log.info(
396                 "WrappedX509Manager: getPrivateKey: "
397                     + this.store.getPrivateKey());
398             return this.store.getPrivateKey();
399         }
400
401         /**
402          * Select the Alias we will authenticate as if Client authentication is
403          * required by the server we are connecting to. We get the list of
404          * aliases, and if there is only one alias we automatically select it.
405          * If there are more than one alias that has a private key, we prompt
406          * the user to choose which alias using a combo box. Otherwise, we
407          * simply provide a text box, which may or may not work. The alias does
408          * have to match one in the keystore.
409          * @see javax.net.ssl.X509KeyManager#chooseClientAlias(java.lang.String, java.security.Principal, java.net.Socket)
410          */

411         public String chooseClientAlias(
412             String[] arg0,
413             Principal[] arg1,
414             Socket arg2)
415         {
416             log.info("Alias: " + this.store.getAlias());
417             return this.store.getAlias();
418         }
419
420         /**
421          * Choose the server alias for the SSLServerSockets. This are not used
422          * in JMeter.
423          * @see javax.net.ssl.X509KeyManager#chooseServerAlias(java.lang.String, java.security.Principal, java.net.Socket)
424          */

425         public String chooseServerAlias(
426             String arg0,
427             Principal[] arg1,
428             Socket arg2)
429         {
430             return this.manager.chooseServerAlias(arg0, arg1);
431         }
432
433         public String chooseClientAlias(String arg0, Principal[] arg1)
434         {
435             return store.getAlias();
436         }
437
438         public String chooseServerAlias(String arg0, Principal[] arg1)
439         {
440             return manager.chooseServerAlias(arg0,arg1);
441         }
442     }
443 }
444
Popular Tags