View Javadoc

1   // ========================================================================
2   // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at 
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses. 
12  // ========================================================================
13  
14  package org.eclipse.jetty.server.ssl;
15  
16  import java.io.ByteArrayInputStream;
17  import java.io.IOException;
18  import java.io.InputStream;
19  import java.nio.channels.SelectionKey;
20  import java.nio.channels.SocketChannel;
21  import java.security.KeyStore;
22  import java.security.SecureRandom;
23  import java.security.cert.X509Certificate;
24  import java.util.ArrayList;
25  import java.util.Arrays;
26  import java.util.List;
27  
28  import javax.net.ssl.KeyManager;
29  import javax.net.ssl.KeyManagerFactory;
30  import javax.net.ssl.SSLContext;
31  import javax.net.ssl.SSLEngine;
32  import javax.net.ssl.SSLPeerUnverifiedException;
33  import javax.net.ssl.SSLSession;
34  import javax.net.ssl.SSLSocket;
35  import javax.net.ssl.TrustManager;
36  import javax.net.ssl.TrustManagerFactory;
37  
38  import org.eclipse.jetty.http.HttpParser;
39  import org.eclipse.jetty.http.HttpSchemes;
40  import org.eclipse.jetty.http.security.Password;
41  import org.eclipse.jetty.http.ssl.SslSelectChannelEndPoint;
42  import org.eclipse.jetty.io.Buffer;
43  import org.eclipse.jetty.io.Buffers;
44  import org.eclipse.jetty.io.Connection;
45  import org.eclipse.jetty.io.EndPoint;
46  import org.eclipse.jetty.io.ThreadLocalBuffers;
47  import org.eclipse.jetty.io.bio.SocketEndPoint;
48  import org.eclipse.jetty.io.nio.DirectNIOBuffer;
49  import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
50  import org.eclipse.jetty.io.nio.SelectorManager.SelectSet;
51  import org.eclipse.jetty.server.HttpConnection;
52  import org.eclipse.jetty.server.Request;
53  import org.eclipse.jetty.server.nio.SelectChannelConnector;
54  import org.eclipse.jetty.util.TypeUtil;
55  import org.eclipse.jetty.util.log.Log;
56  import org.eclipse.jetty.util.resource.Resource;
57  
58  /* ------------------------------------------------------------ */
59  /**
60   * SslSelectChannelConnector.
61   * 
62   * @org.apache.xbean.XBean element="sslConnector" description="Creates an NIO ssl connector"
63   *
64   * 
65   * 
66   */
67  public class SslSelectChannelConnector extends SelectChannelConnector implements SslConnector
68  {
69      /**
70       * The name of the SSLSession attribute that will contain any cached
71       * information.
72       */
73      static final String CACHED_INFO_ATTR=CachedInfo.class.getName();
74  
75      /** Default value for the cipher Suites. */
76      private String _excludeCipherSuites[]=null;
77  
78      /** Default value for the keystore location path. */
79      private String _keystorePath=DEFAULT_KEYSTORE;
80      private String _keystoreType="JKS"; // type of the key store
81  
82      /** Set to true if we require client certificate authentication. */
83      private boolean _needClientAuth=false;
84      private boolean _wantClientAuth=false;
85  
86      private transient Password _password;
87      private transient Password _keyPassword;
88      private transient Password _trustPassword;
89      private String _protocol="TLS";
90      private String _provider;
91      private String _secureRandomAlgorithm; // cert algorithm
92      private String _sslKeyManagerFactoryAlgorithm="SunX509"; 
93      private String _sslTrustManagerFactoryAlgorithm="SunX509"; 
94      private String _truststorePath;
95      private String _truststoreType="JKS"; // type of the key store
96      private SSLContext _context;
97      Buffers _sslBuffers;
98  
99  
100     /**
101      * Return the chain of X509 certificates used to negotiate the SSL Session.
102      * <p>
103      * Note: in order to do this we must convert a
104      * javax.security.cert.X509Certificate[], as used by JSSE to a
105      * java.security.cert.X509Certificate[],as required by the Servlet specs.
106      * 
107      * @param sslSession
108      *                the javax.net.ssl.SSLSession to use as the source of the
109      *                cert chain.
110      * @return the chain of java.security.cert.X509Certificates used to
111      *         negotiate the SSL connection. <br>
112      *         Will be null if the chain is missing or empty.
113      */
114     private static X509Certificate[] getCertChain(SSLSession sslSession)
115     {
116         try
117         {
118             javax.security.cert.X509Certificate javaxCerts[]=sslSession.getPeerCertificateChain();
119             if (javaxCerts==null||javaxCerts.length==0)
120                 return null;
121 
122             int length=javaxCerts.length;
123             X509Certificate[] javaCerts=new X509Certificate[length];
124 
125             java.security.cert.CertificateFactory cf=java.security.cert.CertificateFactory.getInstance("X.509");
126             for (int i=0; i<length; i++)
127             {
128                 byte bytes[]=javaxCerts[i].getEncoded();
129                 ByteArrayInputStream stream=new ByteArrayInputStream(bytes);
130                 javaCerts[i]=(X509Certificate)cf.generateCertificate(stream);
131             }
132 
133             return javaCerts;
134         }
135         catch (SSLPeerUnverifiedException pue)
136         {
137             return null;
138         }
139         catch (Exception e)
140         {
141             Log.warn(Log.EXCEPTION,e);
142             return null;
143         }
144     }
145 
146   
147     /* ------------------------------------------------------------ */
148     /**
149      * Allow the Listener a chance to customise the request. before the server
150      * does its stuff. <br>
151      * This allows the required attributes to be set for SSL requests. <br>
152      * The requirements of the Servlet specs are:
153      * <ul>
154      * <li> an attribute named "javax.servlet.request.ssl_session_id" of type
155      * String (since Servlet Spec 3.0).</li>
156      * <li> an attribute named "javax.servlet.request.cipher_suite" of type
157      * String.</li>
158      * <li> an attribute named "javax.servlet.request.key_size" of type Integer.</li>
159      * <li> an attribute named "javax.servlet.request.X509Certificate" of type
160      * java.security.cert.X509Certificate[]. This is an array of objects of type
161      * X509Certificate, the order of this array is defined as being in ascending
162      * order of trust. The first certificate in the chain is the one set by the
163      * client, the next is the one used to authenticate the first, and so on.
164      * </li>
165      * </ul>
166      * 
167      * @param endpoint
168      *                The Socket the request arrived on. This should be a
169      *                {@link SocketEndPoint} wrapping a {@link SSLSocket}.
170      * @param request
171      *                HttpRequest to be customised.
172      */
173     @Override
174     public void customize(EndPoint endpoint, Request request) throws IOException
175     {
176         super.customize(endpoint,request);
177         request.setScheme(HttpSchemes.HTTPS);
178         
179         SslSelectChannelEndPoint sslHttpChannelEndpoint=(SslSelectChannelEndPoint)endpoint;
180         
181         SSLEngine sslEngine=sslHttpChannelEndpoint.getSSLEngine();
182 
183         try
184         {
185             SSLSession sslSession=sslEngine.getSession();
186             String cipherSuite=sslSession.getCipherSuite();
187             Integer keySize;
188             X509Certificate[] certs;
189             String idStr;
190 
191             CachedInfo cachedInfo=(CachedInfo)sslSession.getValue(CACHED_INFO_ATTR);
192             if (cachedInfo!=null)
193             {
194                 keySize=cachedInfo.getKeySize();
195                 certs=cachedInfo.getCerts();
196                 idStr=cachedInfo.getIdStr();
197             }
198             else
199             {
200                 keySize=new Integer(ServletSSL.deduceKeyLength(cipherSuite));
201                 certs=getCertChain(sslSession);
202                 byte[] bytes = sslSession.getId();
203                 idStr = TypeUtil.toHexString(bytes);
204                 cachedInfo=new CachedInfo(keySize,certs,idStr);
205                 sslSession.putValue(CACHED_INFO_ATTR,cachedInfo);
206             }
207 
208             if (certs!=null)
209                 request.setAttribute("javax.servlet.request.X509Certificate",certs);
210 
211             request.setAttribute("javax.servlet.request.cipher_suite",cipherSuite);
212             request.setAttribute("javax.servlet.request.key_size",keySize);
213             request.setAttribute("javax.servlet.request.ssl_session_id", idStr);
214         }
215         catch (Exception e)
216         {
217             Log.warn(Log.EXCEPTION,e);
218         }
219     }
220 
221     /* ------------------------------------------------------------ */
222     public SslSelectChannelConnector()
223     {
224     }
225 
226     /* ------------------------------------------------------------ */
227     /**
228      * @see org.eclipse.jetty.server.ssl.SslConnector#getExcludeCipherSuites()
229      */
230     public String[] getExcludeCipherSuites()
231     {
232         return _excludeCipherSuites;
233     }
234 
235     /* ------------------------------------------------------------ */
236     /**
237      * @see org.eclipse.jetty.server.ssl.SslConnector#setExcludeCipherSuites(java.lang.String[])
238      */
239     public void setExcludeCipherSuites(String[] cipherSuites)
240     {
241         this._excludeCipherSuites=cipherSuites;
242     }
243 
244     /* ------------------------------------------------------------ */
245     /**
246      * @see org.eclipse.jetty.server.ssl.SslConnector#setPassword(java.lang.String)
247      */
248     public void setPassword(String password)
249     {
250         _password=Password.getPassword(PASSWORD_PROPERTY,password,null);
251     }
252 
253     /* ------------------------------------------------------------ */
254     /**
255      * @see org.eclipse.jetty.server.ssl.SslConnector#setTrustPassword(java.lang.String)
256      */
257     public void setTrustPassword(String password)
258     {
259         _trustPassword=Password.getPassword(PASSWORD_PROPERTY,password,null);
260     }
261 
262     /* ------------------------------------------------------------ */
263     /**
264      * @see org.eclipse.jetty.server.ssl.SslConnector#setKeyPassword(java.lang.String)
265      */
266     public void setKeyPassword(String password)
267     {
268         _keyPassword=Password.getPassword(KEYPASSWORD_PROPERTY,password,null);
269     }
270 
271     /* ------------------------------------------------------------ */
272     /**
273      * @deprecated use {@link #getSslKeyManagerFactoryAlgorithm()} or 
274      * {@link #getSslTrustManagerFactoryAlgorithm()}
275      */
276     public String getAlgorithm()
277     {
278         return getSslKeyManagerFactoryAlgorithm();
279     }
280 
281     /* ------------------------------------------------------------ */
282     /**
283      * @deprecated use {@link #setSslKeyManagerFactoryAlgorithm(String)} or 
284      * {@link #setSslTrustManagerFactoryAlgorithm(String)}
285      */
286     public void setAlgorithm(String algorithm)
287     {
288         setSslKeyManagerFactoryAlgorithm(algorithm);
289         setSslTrustManagerFactoryAlgorithm(algorithm);
290     }
291 
292     /* ------------------------------------------------------------ */
293     /**
294      * @see org.eclipse.jetty.server.ssl.SslConnector#getProtocol()
295      */
296     public String getProtocol()
297     {
298         return _protocol;
299     }
300 
301     /* ------------------------------------------------------------ */
302     /**
303      * @see org.eclipse.jetty.server.ssl.SslConnector#setProtocol(java.lang.String)
304      */
305     public void setProtocol(String protocol)
306     {
307         _protocol=protocol;
308     }
309 
310     /* ------------------------------------------------------------ */
311     /**
312      * @see org.eclipse.jetty.server.ssl.SslConnector#setKeystore(java.lang.String)
313      */
314     public void setKeystore(String keystore)
315     {
316         _keystorePath=keystore;
317     }
318 
319     /* ------------------------------------------------------------ */
320     /**
321      * @see org.eclipse.jetty.server.ssl.SslConnector#getKeystore()
322      */
323     public String getKeystore()
324     {
325         return _keystorePath;
326     }
327 
328     /* ------------------------------------------------------------ */
329     /**
330      * @see org.eclipse.jetty.server.ssl.SslConnector#getKeystoreType()
331      */
332     public String getKeystoreType()
333     {
334         return (_keystoreType);
335     }
336 
337     /* ------------------------------------------------------------ */
338     /**
339      * @see org.eclipse.jetty.server.ssl.SslConnector#getNeedClientAuth()
340      */
341     public boolean getNeedClientAuth()
342     {
343         return _needClientAuth;
344     }
345 
346     /* ------------------------------------------------------------ */
347     /**
348      * @see org.eclipse.jetty.server.ssl.SslConnector#getWantClientAuth()
349      */
350     public boolean getWantClientAuth()
351     {
352         return _wantClientAuth;
353     }
354 
355     /* ------------------------------------------------------------ */
356     /**
357      * @see org.eclipse.jetty.server.ssl.SslConnector#setNeedClientAuth(boolean)
358      */
359     public void setNeedClientAuth(boolean needClientAuth)
360     {
361         _needClientAuth=needClientAuth;
362     }
363 
364     /* ------------------------------------------------------------ */
365     /**
366      * @see org.eclipse.jetty.server.ssl.SslConnector#setWantClientAuth(boolean)
367      */
368     public void setWantClientAuth(boolean wantClientAuth)
369     {
370         _wantClientAuth=wantClientAuth;
371     }
372 
373     /* ------------------------------------------------------------ */
374     /**
375      * @see org.eclipse.jetty.server.ssl.SslConnector#setKeystoreType(java.lang.String)
376      */
377     public void setKeystoreType(String keystoreType)
378     {
379         _keystoreType=keystoreType;
380     }
381 
382     /* ------------------------------------------------------------ */
383     /**
384      * @see org.eclipse.jetty.server.ssl.SslConnector#getProvider()
385      */
386     public String getProvider()
387     {
388         return _provider;
389     }
390 
391     /* ------------------------------------------------------------ */
392     /**
393      * @see org.eclipse.jetty.server.ssl.SslConnector#getSecureRandomAlgorithm()
394      */
395     public String getSecureRandomAlgorithm()
396     {
397         return (this._secureRandomAlgorithm);
398     }
399 
400     /* ------------------------------------------------------------ */
401     /**
402      * @see org.eclipse.jetty.server.ssl.SslConnector#getSslKeyManagerFactoryAlgorithm()
403      */
404     public String getSslKeyManagerFactoryAlgorithm()
405     {
406         return (this._sslKeyManagerFactoryAlgorithm);
407     }
408 
409     /* ------------------------------------------------------------ */
410     /**
411      * @see org.eclipse.jetty.server.ssl.SslConnector#getSslTrustManagerFactoryAlgorithm()
412      */
413     public String getSslTrustManagerFactoryAlgorithm()
414     {
415         return (this._sslTrustManagerFactoryAlgorithm);
416     }
417 
418     /* ------------------------------------------------------------ */
419     /**
420      * @see org.eclipse.jetty.server.ssl.SslConnector#getTruststore()
421      */
422     public String getTruststore()
423     {
424         return _truststorePath;
425     }
426 
427     /* ------------------------------------------------------------ */
428     /**
429      * @see org.eclipse.jetty.server.ssl.SslConnector#getTruststoreType()
430      */
431     public String getTruststoreType()
432     {
433         return _truststoreType;
434     }
435 
436     /* ------------------------------------------------------------ */
437     /**
438      * @see org.eclipse.jetty.server.ssl.SslConnector#setProvider(java.lang.String)
439      */
440     public void setProvider(String provider)
441     {
442         _provider=provider;
443     }
444 
445     /* ------------------------------------------------------------ */
446     /**
447      * @see org.eclipse.jetty.server.ssl.SslConnector#setSecureRandomAlgorithm(java.lang.String)
448      */
449     public void setSecureRandomAlgorithm(String algorithm)
450     {
451         this._secureRandomAlgorithm=algorithm;
452     }
453 
454     /* ------------------------------------------------------------ */
455     /**
456      * @see org.eclipse.jetty.server.ssl.SslConnector#setSslKeyManagerFactoryAlgorithm(java.lang.String)
457      */
458     public void setSslKeyManagerFactoryAlgorithm(String algorithm)
459     {
460         this._sslKeyManagerFactoryAlgorithm=algorithm;
461     }
462 
463     /* ------------------------------------------------------------ */
464     /**
465      * @see org.eclipse.jetty.server.ssl.SslConnector#setSslTrustManagerFactoryAlgorithm(java.lang.String)
466      */
467     public void setSslTrustManagerFactoryAlgorithm(String algorithm)
468     {
469         this._sslTrustManagerFactoryAlgorithm=algorithm;
470     }
471 
472     /* ------------------------------------------------------------ */
473     /**
474      * @see org.eclipse.jetty.server.ssl.SslConnector#setTruststore(java.lang.String)
475      */
476     public void setTruststore(String truststore)
477     {
478         _truststorePath=truststore;
479     }
480 
481     /* ------------------------------------------------------------ */
482     /**
483      * @see org.eclipse.jetty.server.ssl.SslConnector#setTruststoreType(java.lang.String)
484      */
485     public void setTruststoreType(String truststoreType)
486     {
487         _truststoreType=truststoreType;
488     }
489 
490     /* ------------------------------------------------------------ */
491     /**
492      * @see org.eclipse.jetty.server.ssl.SslConnector#setSslContext(javax.net.ssl.SSLContext)
493      */
494     public void setSslContext(SSLContext sslContext) 
495     {
496         _context = sslContext;
497     }
498 
499     /* ------------------------------------------------------------ */
500     /**
501      * @throws Exception 
502      * @see org.eclipse.jetty.server.ssl.SslConnector#setSslContext(javax.net.ssl.SSLContext)
503      */
504     public SSLContext getSslContext()
505     {
506         try
507         {
508             if (_context == null)
509                 _context=createSSLContext();
510         }
511         catch(Exception e)
512         {
513             throw new RuntimeException(e);
514         }
515          
516         return _context;
517     }
518 
519     /* ------------------------------------------------------------ */
520     /**
521      * By default, we're confidential, given we speak SSL. But, if we've been
522      * told about an confidential port, and said port is not our port, then
523      * we're not. This allows separation of listeners providing INTEGRAL versus
524      * CONFIDENTIAL constraints, such as one SSL listener configured to require
525      * client certs providing CONFIDENTIAL, whereas another SSL listener not
526      * requiring client certs providing mere INTEGRAL constraints.
527      */
528     public boolean isConfidential(Request request)
529     {
530         final int confidentialPort=getConfidentialPort();
531         return confidentialPort==0||confidentialPort==request.getServerPort();
532     }
533 
534     /* ------------------------------------------------------------ */
535     /**
536      * By default, we're integral, given we speak SSL. But, if we've been told
537      * about an integral port, and said port is not our port, then we're not.
538      * This allows separation of listeners providing INTEGRAL versus
539      * CONFIDENTIAL constraints, such as one SSL listener configured to require
540      * client certs providing CONFIDENTIAL, whereas another SSL listener not
541      * requiring client certs providing mere INTEGRAL constraints.
542      */
543     public boolean isIntegral(Request request)
544     {
545         final int integralPort=getIntegralPort();
546         return integralPort==0||integralPort==request.getServerPort();
547     }
548 
549     /* ------------------------------------------------------------------------------- */
550     protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key) throws IOException
551     {
552         return new SslSelectChannelEndPoint(_sslBuffers,channel,selectSet,key,createSSLEngine());
553     }
554 
555     /* ------------------------------------------------------------------------------- */
556     protected Connection newConnection(SocketChannel channel, SelectChannelEndPoint endpoint)
557     {
558         HttpConnection connection=(HttpConnection)super.newConnection(channel,endpoint);
559         ((HttpParser)connection.getParser()).setForceContentBuffer(true);
560         return connection;
561     }
562 
563     /* ------------------------------------------------------------ */
564     protected SSLEngine createSSLEngine() throws IOException
565     {
566         SSLEngine engine=null;
567         try
568         {
569             engine=_context.createSSLEngine();
570             engine.setUseClientMode(false);
571             
572             if (_wantClientAuth)
573                 engine.setWantClientAuth(_wantClientAuth);
574             if (_needClientAuth)
575                 engine.setNeedClientAuth(_needClientAuth);
576             
577             if (_excludeCipherSuites!=null&&_excludeCipherSuites.length>0)
578             {
579                 List<String> excludedCSList=Arrays.asList(_excludeCipherSuites);
580                 String[] enabledCipherSuites=engine.getEnabledCipherSuites();
581                 List<String> enabledCSList=new ArrayList<String>(Arrays.asList(enabledCipherSuites));
582 
583                 for (String cipherName : excludedCSList)
584                 {
585                     if (enabledCSList.contains(cipherName))
586                     {
587                         enabledCSList.remove(cipherName);
588                     }
589                 }
590                 enabledCipherSuites=enabledCSList.toArray(new String[enabledCSList.size()]);
591 
592                 engine.setEnabledCipherSuites(enabledCipherSuites);
593             }
594 
595         }
596         catch (Exception e)
597         {
598             Log.warn("Error creating sslEngine -- closing this connector",e);
599             close();
600             throw new IllegalStateException(e);
601         }
602         return engine;
603     }
604 
605    
606     protected void doStart() throws Exception
607     {
608     	if (_context == null)
609            _context=createSSLContext();
610         
611         SSLEngine engine=createSSLEngine();
612         SSLSession ssl_session=engine.getSession();
613         
614         ThreadLocalBuffers buffers = new ThreadLocalBuffers()
615         {
616             @Override
617             protected Buffer newBuffer(int size)
618             {
619                 // TODO indirect?
620                 return new DirectNIOBuffer(size);
621             }
622             @Override
623             protected Buffer newHeader(int size)
624             {
625                 // TODO indirect?
626                 return new DirectNIOBuffer(size);
627             }
628             @Override
629             protected boolean isHeader(Buffer buffer)
630             {
631                 return true;
632             }
633         };
634         buffers.setBufferSize(ssl_session.getApplicationBufferSize());
635         buffers.setHeaderSize(ssl_session.getApplicationBufferSize());
636         _sslBuffers=buffers;
637         
638         if (getRequestHeaderSize()<ssl_session.getApplicationBufferSize())
639             setRequestHeaderSize(ssl_session.getApplicationBufferSize());
640         if (getRequestBufferSize()<ssl_session.getApplicationBufferSize())
641             setRequestBufferSize(ssl_session.getApplicationBufferSize());
642         
643         super.doStart();
644     }
645 
646     /* ------------------------------------------------------------ */
647     protected SSLContext createSSLContext() throws Exception
648     {
649         KeyManager[] keyManagers=getKeyManagers();
650 
651         TrustManager[] trustManagers=getTrustManagers();
652 
653         SecureRandom secureRandom=_secureRandomAlgorithm==null?null:SecureRandom.getInstance(_secureRandomAlgorithm);
654         SSLContext context=_provider==null?SSLContext.getInstance(_protocol):SSLContext.getInstance(_protocol,_provider);
655         context.init(keyManagers,trustManagers,secureRandom);
656         return context;
657     }
658 
659     /* ------------------------------------------------------------ */
660     protected KeyManager[] getKeyManagers() throws Exception
661     {
662         KeyStore keyStore = getKeyStore(_keystorePath, _keystoreType, _password==null?null:_password.toString());
663         
664         KeyManagerFactory keyManagerFactory=KeyManagerFactory.getInstance(_sslKeyManagerFactoryAlgorithm);
665         keyManagerFactory.init(keyStore,_keyPassword==null?(_password==null?null:_password.toString().toCharArray()):_keyPassword.toString().toCharArray());
666         return keyManagerFactory.getKeyManagers();
667     }
668 
669     /* ------------------------------------------------------------ */
670     protected TrustManager[] getTrustManagers() throws Exception
671     {        
672         if (_truststorePath==null)
673         {
674             _truststorePath=_keystorePath;
675             _truststoreType=_keystoreType;
676             _trustPassword = _password;
677             _sslTrustManagerFactoryAlgorithm = _sslKeyManagerFactoryAlgorithm;
678         }
679         
680         KeyStore trustStore = getKeyStore(_truststorePath, _truststoreType, _trustPassword==null?null:_trustPassword.toString());
681 
682         TrustManagerFactory trustManagerFactory=TrustManagerFactory.getInstance(_sslTrustManagerFactoryAlgorithm);
683         trustManagerFactory.init(trustStore);
684         return trustManagerFactory.getTrustManagers();
685     }
686 
687     /* ------------------------------------------------------------ */
688     protected KeyStore getKeyStore(String keystorePath, String keystoreType, String keystorePassword) throws Exception
689     {
690     	KeyStore keystore;
691     	InputStream keystoreInputStream = null;
692     	try
693         {
694             if (keystorePath!=null)
695                 keystoreInputStream = Resource.newResource(keystorePath).getInputStream();
696             keystore=KeyStore.getInstance(keystoreType);
697             keystore.load(keystoreInputStream,keystorePassword==null?null:keystorePassword.toString().toCharArray());
698             return keystore;
699         }
700         finally
701         {
702             if (keystoreInputStream != null)
703             	keystoreInputStream.close();
704         }
705     }
706 
707     /* ------------------------------------------------------------ */
708     /* ------------------------------------------------------------ */
709     /* ------------------------------------------------------------ */
710     /**
711      * Simple bundle of information that is cached in the SSLSession. Stores the
712      * effective keySize and the client certificate chain.
713      */
714     private class CachedInfo
715     {
716         private final X509Certificate[] _certs;
717         private final Integer _keySize;
718         private final String _idStr;
719 
720         CachedInfo(Integer keySize, X509Certificate[] certs,String idStr)
721         {
722             this._keySize=keySize;
723             this._certs=certs;
724             this._idStr=idStr;
725         }
726 
727         X509Certificate[] getCerts()
728         {
729             return _certs;
730         }
731 
732         Integer getKeySize()
733         {
734             return _keySize;
735         }
736         
737         String getIdStr()
738         {
739             return _idStr;
740         }
741     }
742 
743 }