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