View Javadoc

1   //========================================================================
2   //Copyright (c) Webtide LLC
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   //
8   //The Eclipse Public License is available at
9   //http://www.eclipse.org/legal/epl-v10.html
10  //
11  //The Apache License v2.0 is available at
12  //http://www.apache.org/licenses/LICENSE-2.0.txt
13  //
14  //You may elect to redistribute this code under either of these licenses.
15  //========================================================================
16  
17  package org.eclipse.jetty.http.ssl;
18  
19  import java.io.ByteArrayInputStream;
20  import java.io.ByteArrayOutputStream;
21  import java.io.File;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.net.InetAddress;
25  import java.security.InvalidParameterException;
26  import java.security.KeyStore;
27  import java.security.SecureRandom;
28  import java.security.Security;
29  import java.security.cert.CRL;
30  import java.security.cert.CertStore;
31  import java.security.cert.Certificate;
32  import java.security.cert.CollectionCertStoreParameters;
33  import java.security.cert.PKIXBuilderParameters;
34  import java.security.cert.X509CertSelector;
35  import java.util.Arrays;
36  import java.util.Collection;
37  import java.util.Collections;
38  import java.util.HashSet;
39  import java.util.List;
40  import java.util.Set;
41  import javax.net.ssl.CertPathTrustManagerParameters;
42  import javax.net.ssl.KeyManager;
43  import javax.net.ssl.KeyManagerFactory;
44  import javax.net.ssl.SSLContext;
45  import javax.net.ssl.SSLEngine;
46  import javax.net.ssl.SSLServerSocket;
47  import javax.net.ssl.SSLServerSocketFactory;
48  import javax.net.ssl.SSLSocket;
49  import javax.net.ssl.SSLSocketFactory;
50  import javax.net.ssl.TrustManager;
51  import javax.net.ssl.TrustManagerFactory;
52  import javax.net.ssl.X509KeyManager;
53  import javax.net.ssl.X509TrustManager;
54  
55  import org.eclipse.jetty.http.security.Password;
56  import org.eclipse.jetty.util.IO;
57  import org.eclipse.jetty.util.component.AbstractLifeCycle;
58  import org.eclipse.jetty.util.log.Log;
59  import org.eclipse.jetty.util.log.Logger;
60  import org.eclipse.jetty.util.resource.Resource;
61  import org.eclipse.jetty.util.security.CertificateUtils;
62  import org.eclipse.jetty.util.security.CertificateValidator;
63  
64  
65  /* ------------------------------------------------------------ */
66  /**
67   * SslContextFactory is used to configure SSL connectors
68   * as well as HttpClient. It holds all SSL parameters and
69   * creates SSL context based on these parameters to be
70   * used by the SSL connectors.
71   */
72  public class SslContextFactory extends AbstractLifeCycle
73  {
74      private static final Logger LOG = Log.getLogger(SslContextFactory.class);
75      
76      public static final String DEFAULT_KEYMANAGERFACTORY_ALGORITHM =
77          (Security.getProperty("ssl.KeyManagerFactory.algorithm") == null ?
78                  "SunX509" : Security.getProperty("ssl.KeyManagerFactory.algorithm"));
79      public static final String DEFAULT_TRUSTMANAGERFACTORY_ALGORITHM =
80          (Security.getProperty("ssl.TrustManagerFactory.algorithm") == null ?
81                  "SunX509" : Security.getProperty("ssl.TrustManagerFactory.algorithm"));
82  
83      /** Default value for the keystore location path. */
84      public static final String DEFAULT_KEYSTORE_PATH =
85          System.getProperty("user.home") + File.separator + ".keystore";
86  
87      /** String name of key password property. */
88      public static final String KEYPASSWORD_PROPERTY = "org.eclipse.jetty.ssl.keypassword";
89  
90      /** String name of keystore password property. */
91      public static final String PASSWORD_PROPERTY = "org.eclipse.jetty.ssl.password";
92  
93      /** Excluded protocols. */
94      private final Set<String> _excludeProtocols = new HashSet<String>();
95      // private final Set<String> _excludeProtocols = new HashSet<String>(Collections.singleton("SSLv2Hello"));
96      /** Included protocols. */
97      private Set<String> _includeProtocols = null;
98      
99      /** Excluded cipher suites. */
100     private final Set<String> _excludeCipherSuites = new HashSet<String>();
101     /** Included cipher suites. */
102     private Set<String> _includeCipherSuites = null;
103 
104     /** Keystore path. */
105     private String _keyStorePath;
106     /** Keystore provider name */
107     private String _keyStoreProvider;
108     /** Keystore type */
109     private String _keyStoreType = "JKS";
110     /** Keystore input stream */
111     private InputStream _keyStoreInputStream;
112 
113     /** SSL certificate alias */
114     private String _certAlias;
115 
116     /** Truststore path */
117     private String _trustStorePath;
118     /** Truststore provider name */
119     private String _trustStoreProvider;
120     /** Truststore type */
121     private String _trustStoreType = "JKS";
122     /** Truststore input stream */
123     private InputStream _trustStoreInputStream;
124 
125     /** Set to true if client certificate authentication is required */
126     private boolean _needClientAuth = false;
127     /** Set to true if client certificate authentication is desired */
128     private boolean _wantClientAuth = false;
129 
130     /** Set to true if renegotiation is allowed */
131     private boolean _allowRenegotiate = true;
132 
133     /** Keystore password */
134     private transient Password _keyStorePassword;
135     /** Key manager password */
136     private transient Password _keyManagerPassword;
137     /** Truststore password */
138     private transient Password _trustStorePassword;
139 
140     /** SSL provider name */
141     private String _sslProvider;
142     /** SSL protocol name */
143     private String _sslProtocol = "TLS";
144 
145     /** SecureRandom algorithm */
146     private String _secureRandomAlgorithm;
147     /** KeyManager factory algorithm */
148     private String _keyManagerFactoryAlgorithm = DEFAULT_KEYMANAGERFACTORY_ALGORITHM;
149     /** TrustManager factory algorithm */
150     private String _trustManagerFactoryAlgorithm = DEFAULT_TRUSTMANAGERFACTORY_ALGORITHM;
151 
152     /** Set to true if SSL certificate validation is required */
153     private boolean _validateCerts;
154     /** Set to true if SSL certificate of the peer validation is required */
155     private boolean _validatePeerCerts;
156     /** Maximum certification path length (n - number of intermediate certs, -1 for unlimited) */
157     private int _maxCertPathLength = -1;
158     /** Path to file that contains Certificate Revocation List */
159     private String _crlPath;
160     /** Set to true to enable CRL Distribution Points (CRLDP) support */
161     private boolean _enableCRLDP = false;
162     /** Set to true to enable On-Line Certificate Status Protocol (OCSP) support */
163     private boolean _enableOCSP = false;
164     /** Location of OCSP Responder */
165     private String _ocspResponderURL;
166 
167     /** SSL keystore */
168     private KeyStore _keyStore;
169     /** SSL truststore */
170     private KeyStore _trustStore;
171     /** Set to true to enable SSL Session caching */
172     private boolean _sessionCachingEnabled = true;
173     /** SSL session cache size */
174     private int _sslSessionCacheSize;
175     /** SSL session timeout */
176     private int _sslSessionTimeout;
177 
178     /** SSL context */
179     private SSLContext _context;
180 
181     /* ------------------------------------------------------------ */
182     /**
183      * Construct an instance of SslContextFactory
184      * Default constructor for use in XmlConfiguration files
185      */
186     public SslContextFactory()
187     {
188     }
189 
190     /* ------------------------------------------------------------ */
191     /**
192      * Construct an instance of SslContextFactory
193      * @param keyStorePath default keystore location
194      */
195     public SslContextFactory(String keyStorePath)
196     {
197         _keyStorePath = keyStorePath;
198     }
199 
200     /* ------------------------------------------------------------ */
201     /**
202      * Create the SSLContext object and start the lifecycle
203      * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
204      */
205     @Override
206     protected void doStart() throws Exception
207     {
208         if (_context == null)
209         {
210             if (_keyStoreInputStream == null && _keyStorePath == null &&
211                     _trustStoreInputStream == null && _trustStorePath == null )
212             {
213                 LOG.debug("No keystore or trust store configured.  ACCEPTING UNTRUSTED CERTIFICATES!!!!!");
214                 // Create a trust manager that does not validate certificate chains
215                 TrustManager trustAllCerts = new X509TrustManager()
216                 {
217                     public java.security.cert.X509Certificate[] getAcceptedIssuers()
218                     {
219                         return null;
220                     }
221 
222                     public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
223                     {
224                     }
225 
226                     public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
227                     {
228                     }
229                 };
230 
231                 _context = SSLContext.getInstance(_sslProtocol);
232                 _context.init(null, new TrustManager[]{trustAllCerts}, null);
233             }
234             else
235             {
236                 // verify that keystore and truststore
237                 // parameters are set up correctly
238                 try
239                 {
240                     checkKeyStore();
241                 }
242                 catch(IllegalStateException e)
243                 {
244                     LOG.ignore(e);
245                 }
246 
247                 KeyStore keyStore = loadKeyStore();
248                 KeyStore trustStore = loadTrustStore();
249 
250                 Collection<? extends CRL> crls = loadCRL(_crlPath);
251 
252                 if (_validateCerts && keyStore != null)
253                 {
254                     if (_certAlias == null)
255                     {
256                         List<String> aliases = Collections.list(keyStore.aliases());
257                         _certAlias = aliases.size() == 1 ? aliases.get(0) : null;
258                     }
259 
260                     Certificate cert = _certAlias == null?null:keyStore.getCertificate(_certAlias);
261                     if (cert == null)
262                     {
263                         throw new Exception("No certificate found in the keystore" + (_certAlias==null ? "":" for alias " + _certAlias));
264                     }
265 
266                     CertificateValidator validator = new CertificateValidator(trustStore, crls);
267                     validator.setMaxCertPathLength(_maxCertPathLength);
268                     validator.setEnableCRLDP(_enableCRLDP);
269                     validator.setEnableOCSP(_enableOCSP);
270                     validator.setOcspResponderURL(_ocspResponderURL);
271                     validator.validate(keyStore, cert);
272                 }
273 
274                 KeyManager[] keyManagers = getKeyManagers(keyStore);
275                 TrustManager[] trustManagers = getTrustManagers(trustStore,crls);
276 
277                 SecureRandom secureRandom = (_secureRandomAlgorithm == null)?null:SecureRandom.getInstance(_secureRandomAlgorithm);
278                 _context = (_sslProvider == null)?SSLContext.getInstance(_sslProtocol):SSLContext.getInstance(_sslProtocol,_sslProvider);
279                 _context.init(keyManagers,trustManagers,secureRandom);
280 
281                 SSLEngine engine=newSslEngine();
282                 LOG.info("Enabled Protocols {} of {}",Arrays.asList(engine.getEnabledProtocols()),Arrays.asList(engine.getSupportedProtocols()));
283                 LOG.debug("Enabled Ciphers   {} of {}",Arrays.asList(engine.getEnabledCipherSuites()),Arrays.asList(engine.getSupportedCipherSuites()));
284             }
285         }
286     }
287 
288     /* ------------------------------------------------------------ */
289     /**
290      * @return The array of protocol names to exclude from
291      * {@link SSLEngine#setEnabledProtocols(String[])}
292      */
293     public String[] getExcludeProtocols()
294     {
295         return _excludeProtocols.toArray(new String[_excludeProtocols.size()]);
296     }
297 
298     /* ------------------------------------------------------------ */
299     /**
300      * @param Protocols
301      *            The array of protocol names to exclude from
302      *            {@link SSLEngine#setEnabledProtocols(String[])}
303      */
304     public void setExcludeProtocols(String... protocols)
305     {
306         checkNotStarted();
307 
308         _excludeProtocols.clear();
309         _excludeProtocols.addAll(Arrays.asList(protocols));
310     }
311 
312     /* ------------------------------------------------------------ */
313     /**
314      * @param protocol Protocol names to add to {@link SSLEngine#setEnabledProtocols(String[])}
315      */
316     public void addExcludeProtocols(String... protocol)
317     {
318         checkNotStarted();
319         _excludeProtocols.addAll(Arrays.asList(protocol));
320     }
321     
322     /* ------------------------------------------------------------ */
323     /**
324      * @return The array of protocol names to include in
325      * {@link SSLEngine#setEnabledProtocols(String[])}
326      */
327     public String[] getIncludeProtocols()
328     {
329         return _includeProtocols.toArray(new String[_includeProtocols.size()]);
330     }
331 
332     /* ------------------------------------------------------------ */
333     /**
334      * @param Protocols
335      *            The array of protocol names to include in
336      *            {@link SSLEngine#setEnabledProtocols(String[])}
337      */
338     public void setIncludeProtocols(String... protocols)
339     {
340         checkNotStarted();
341 
342         _includeProtocols = new HashSet<String>(Arrays.asList(protocols));
343     }
344 
345     /* ------------------------------------------------------------ */
346     /**
347      * @return The array of cipher suite names to exclude from
348      * {@link SSLEngine#setEnabledCipherSuites(String[])}
349      */
350     public String[] getExcludeCipherSuites()
351     {
352         return _excludeCipherSuites.toArray(new String[_excludeCipherSuites.size()]);
353     }
354 
355     /* ------------------------------------------------------------ */
356     /**
357      * @param cipherSuites
358      *            The array of cipher suite names to exclude from
359      *            {@link SSLEngine#setEnabledCipherSuites(String[])}
360      */
361     public void setExcludeCipherSuites(String... cipherSuites)
362     {
363         checkNotStarted();
364         _excludeCipherSuites.clear();
365         _excludeCipherSuites.addAll(Arrays.asList(cipherSuites));
366     }
367     
368     /* ------------------------------------------------------------ */
369     /**
370      * @param cipher Cipher names to add to {@link SSLEngine#setEnabledCipherSuites(String[])}
371      */
372     public void addExcludeCipherSuites(String... cipher)
373     {
374         checkNotStarted();
375         _excludeCipherSuites.addAll(Arrays.asList(cipher));
376     }
377 
378     /* ------------------------------------------------------------ */
379     /**
380      * @return The array of cipher suite names to include in
381      * {@link SSLEngine#setEnabledCipherSuites(String[])}
382      */
383     public String[] getIncludeCipherSuites()
384     {
385         return _includeCipherSuites.toArray(new String[_includeCipherSuites.size()]);
386     }
387 
388     /* ------------------------------------------------------------ */
389     /**
390      * @param cipherSuites
391      *            The array of cipher suite names to include in
392      *            {@link SSLEngine#setEnabledCipherSuites(String[])}
393      */
394     public void setIncludeCipherSuites(String... cipherSuites)
395     {
396         checkNotStarted();
397 
398         _includeCipherSuites = new HashSet<String>(Arrays.asList(cipherSuites));
399     }
400 
401     /* ------------------------------------------------------------ */
402     /**
403      * @return The file or URL of the SSL Key store.
404      */
405     public String getKeyStore()
406     {
407         return _keyStorePath;
408     }
409 
410     /* ------------------------------------------------------------ */
411     /**
412      * @param keyStorePath
413      *            The file or URL of the SSL Key store.
414      */
415     public void setKeyStore(String keyStorePath)
416     {
417         checkNotStarted();
418 
419         _keyStorePath = keyStorePath;
420     }
421 
422     /* ------------------------------------------------------------ */
423     /**
424      * @return The provider of the key store
425      */
426     public String getKeyStoreProvider()
427     {
428         return _keyStoreProvider;
429     }
430 
431     /* ------------------------------------------------------------ */
432     /**
433      * @param keyStoreProvider
434      *            The provider of the key store
435      */
436     public void setKeyStoreProvider(String keyStoreProvider)
437     {
438         checkNotStarted();
439 
440         _keyStoreProvider = keyStoreProvider;
441     }
442 
443     /* ------------------------------------------------------------ */
444     /**
445      * @return The type of the key store (default "JKS")
446      */
447     public String getKeyStoreType()
448     {
449         return (_keyStoreType);
450     }
451 
452     /* ------------------------------------------------------------ */
453     /**
454      * @param keyStoreType
455      *            The type of the key store (default "JKS")
456      */
457     public void setKeyStoreType(String keyStoreType)
458     {
459         checkNotStarted();
460 
461         _keyStoreType = keyStoreType;
462     }
463 
464     /* ------------------------------------------------------------ */
465     /** Get the _keyStoreInputStream.
466      * @return the _keyStoreInputStream
467      *
468      * @deprecated
469      */
470     @Deprecated
471     public InputStream getKeyStoreInputStream()
472     {
473         checkKeyStore();
474 
475         return _keyStoreInputStream;
476     }
477 
478     /* ------------------------------------------------------------ */
479     /** Set the keyStoreInputStream.
480      * @param keyStoreInputStream the InputStream to the KeyStore
481      *
482      * @deprecated
483      */
484     @Deprecated
485     public void setKeyStoreInputStream(InputStream keyStoreInputStream)
486     {
487         checkNotStarted();
488 
489         _keyStoreInputStream = keyStoreInputStream;
490     }
491 
492     /* ------------------------------------------------------------ */
493     /**
494      * @return Alias of SSL certificate for the connector
495      */
496     public String getCertAlias()
497     {
498         return _certAlias;
499     }
500 
501     /* ------------------------------------------------------------ */
502     /**
503      * @param certAlias
504      *            Alias of SSL certificate for the connector
505      */
506     public void setCertAlias(String certAlias)
507     {
508         checkNotStarted();
509 
510         _certAlias = certAlias;
511     }
512 
513     /* ------------------------------------------------------------ */
514     /**
515      * @return The file name or URL of the trust store location
516      */
517     public String getTrustStore()
518     {
519         return _trustStorePath;
520     }
521 
522     /* ------------------------------------------------------------ */
523     /**
524      * @param trustStorePath
525      *            The file name or URL of the trust store location
526      */
527     public void setTrustStore(String trustStorePath)
528     {
529         checkNotStarted();
530 
531         _trustStorePath = trustStorePath;
532     }
533 
534     /* ------------------------------------------------------------ */
535     /**
536      * @return The provider of the trust store
537      */
538     public String getTrustStoreProvider()
539     {
540         return _trustStoreProvider;
541     }
542 
543     /* ------------------------------------------------------------ */
544     /**
545      * @param trustStoreProvider
546      *            The provider of the trust store
547      */
548     public void setTrustStoreProvider(String trustStoreProvider)
549     {
550         checkNotStarted();
551 
552         _trustStoreProvider = trustStoreProvider;
553     }
554 
555     /* ------------------------------------------------------------ */
556     /**
557      * @return The type of the trust store (default "JKS")
558      */
559     public String getTrustStoreType()
560     {
561         return _trustStoreType;
562     }
563 
564     /* ------------------------------------------------------------ */
565     /**
566      * @param trustStoreType
567      *            The type of the trust store (default "JKS")
568      */
569     public void setTrustStoreType(String trustStoreType)
570     {
571         checkNotStarted();
572 
573         _trustStoreType = trustStoreType;
574     }
575 
576     /* ------------------------------------------------------------ */
577     /** Get the _trustStoreInputStream.
578      * @return the _trustStoreInputStream
579      *
580      * @deprecated
581      */
582     @Deprecated
583     public InputStream getTrustStoreInputStream()
584     {
585         checkKeyStore();
586 
587         return _trustStoreInputStream;
588     }
589 
590     /* ------------------------------------------------------------ */
591     /** Set the _trustStoreInputStream.
592      * @param trustStoreInputStream the InputStream to the TrustStore
593      *
594      * @deprecated
595      */
596     @Deprecated
597     public void setTrustStoreInputStream(InputStream trustStoreInputStream)
598     {
599         checkNotStarted();
600 
601         _trustStoreInputStream = trustStoreInputStream;
602     }
603 
604     /* ------------------------------------------------------------ */
605     /**
606      * @return True if SSL needs client authentication.
607      * @see SSLEngine#getNeedClientAuth()
608      */
609     public boolean getNeedClientAuth()
610     {
611         return _needClientAuth;
612     }
613 
614     /* ------------------------------------------------------------ */
615     /**
616      * @param needClientAuth
617      *            True if SSL needs client authentication.
618      * @see SSLEngine#getNeedClientAuth()
619      */
620     public void setNeedClientAuth(boolean needClientAuth)
621     {
622         checkNotStarted();
623 
624         _needClientAuth = needClientAuth;
625     }
626 
627     /* ------------------------------------------------------------ */
628     /**
629      * @return True if SSL wants client authentication.
630      * @see SSLEngine#getWantClientAuth()
631      */
632     public boolean getWantClientAuth()
633     {
634         return _wantClientAuth;
635     }
636 
637     /* ------------------------------------------------------------ */
638     /**
639      * @param wantClientAuth
640      *            True if SSL wants client authentication.
641      * @see SSLEngine#getWantClientAuth()
642      */
643     public void setWantClientAuth(boolean wantClientAuth)
644     {
645         checkNotStarted();
646 
647         _wantClientAuth = wantClientAuth;
648     }
649 
650     /* ------------------------------------------------------------ */
651     /**
652      * @return true if SSL certificate has to be validated
653      * @deprecated
654      */
655     @Deprecated
656     public boolean getValidateCerts()
657     {
658         return _validateCerts;
659     }
660 
661     /* ------------------------------------------------------------ */
662     /**
663      * @return true if SSL certificate has to be validated
664      */
665     public boolean isValidateCerts()
666     {
667         return _validateCerts;
668     }
669 
670     /* ------------------------------------------------------------ */
671     /**
672      * @param validateCerts
673      *            true if SSL certificates have to be validated
674      */
675     public void setValidateCerts(boolean validateCerts)
676     {
677         checkNotStarted();
678 
679         _validateCerts = validateCerts;
680     }
681 
682     /* ------------------------------------------------------------ */
683     /**
684      * @return true if SSL certificates of the peer have to be validated
685      */
686     public boolean isValidatePeerCerts()
687     {
688         return _validatePeerCerts;
689     }
690 
691     /* ------------------------------------------------------------ */
692     /**
693      * @param validatePeerCerts
694      *            true if SSL certificates of the peer have to be validated
695      */
696     public void setValidatePeerCerts(boolean validatePeerCerts)
697     {
698         checkNotStarted();
699 
700         _validatePeerCerts = validatePeerCerts;
701     }
702 
703     /* ------------------------------------------------------------ */
704     /**
705      * @return True if SSL re-negotiation is allowed (default false)
706      */
707     public boolean isAllowRenegotiate()
708     {
709         return _allowRenegotiate;
710     }
711 
712     /* ------------------------------------------------------------ */
713     /**
714      * Set if SSL re-negotiation is allowed. CVE-2009-3555 discovered
715      * a vulnerability in SSL/TLS with re-negotiation.  If your JVM
716      * does not have CVE-2009-3555 fixed, then re-negotiation should
717      * not be allowed.  CVE-2009-3555 was fixed in Sun java 1.6 with a ban
718      * of renegotiates in u19 and with RFC5746 in u22.
719      *
720      * @param allowRenegotiate
721      *            true if re-negotiation is allowed (default false)
722      */
723     public void setAllowRenegotiate(boolean allowRenegotiate)
724     {
725         checkNotStarted();
726 
727         _allowRenegotiate = allowRenegotiate;
728     }
729 
730     /* ------------------------------------------------------------ */
731     /**
732      * @param password
733      *            The password for the key store
734      */
735     public void setKeyStorePassword(String password)
736     {
737         checkNotStarted();
738 
739         _keyStorePassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
740     }
741 
742     /* ------------------------------------------------------------ */
743     /**
744      * @param password
745      *            The password (if any) for the specific key within the key store
746      */
747     public void setKeyManagerPassword(String password)
748     {
749         checkNotStarted();
750 
751         _keyManagerPassword = Password.getPassword(KEYPASSWORD_PROPERTY,password,null);
752     }
753 
754     /* ------------------------------------------------------------ */
755     /**
756      * @param password
757      *            The password for the trust store
758      */
759     public void setTrustStorePassword(String password)
760     {
761         checkNotStarted();
762 
763         _trustStorePassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
764     }
765 
766     /* ------------------------------------------------------------ */
767     /**
768      * @return The SSL provider name, which if set is passed to
769      * {@link SSLContext#getInstance(String, String)}
770      */
771     public String getProvider()
772     {
773         return _sslProvider;
774     }
775 
776     /* ------------------------------------------------------------ */
777     /**
778      * @param provider
779      *            The SSL provider name, which if set is passed to
780      *            {@link SSLContext#getInstance(String, String)}
781      */
782     public void setProvider(String provider)
783     {
784         checkNotStarted();
785 
786         _sslProvider = provider;
787     }
788 
789     /* ------------------------------------------------------------ */
790     /**
791      * @return The SSL protocol (default "TLS") passed to
792      * {@link SSLContext#getInstance(String, String)}
793      */
794     public String getProtocol()
795     {
796         return _sslProtocol;
797     }
798 
799     /* ------------------------------------------------------------ */
800     /**
801      * @param protocol
802      *            The SSL protocol (default "TLS") passed to
803      *            {@link SSLContext#getInstance(String, String)}
804      */
805     public void setProtocol(String protocol)
806     {
807         checkNotStarted();
808 
809         _sslProtocol = protocol;
810     }
811 
812     /* ------------------------------------------------------------ */
813     /**
814      * @return The algorithm name, which if set is passed to
815      * {@link SecureRandom#getInstance(String)} to obtain the {@link SecureRandom} instance passed to
816      * {@link SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], SecureRandom)}
817      */
818     public String getSecureRandomAlgorithm()
819     {
820         return _secureRandomAlgorithm;
821     }
822 
823     /* ------------------------------------------------------------ */
824     /**
825      * @param algorithm
826      *            The algorithm name, which if set is passed to
827      *            {@link SecureRandom#getInstance(String)} to obtain the {@link SecureRandom} instance passed to
828      *            {@link SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], SecureRandom)}
829      */
830     public void setSecureRandomAlgorithm(String algorithm)
831     {
832         checkNotStarted();
833 
834         _secureRandomAlgorithm = algorithm;
835     }
836 
837     /* ------------------------------------------------------------ */
838     /**
839      * @return The algorithm name (default "SunX509") used by the {@link KeyManagerFactory}
840      */
841     public String getSslKeyManagerFactoryAlgorithm()
842     {
843         return (_keyManagerFactoryAlgorithm);
844     }
845 
846     /* ------------------------------------------------------------ */
847     /**
848      * @param algorithm
849      *            The algorithm name (default "SunX509") used by the {@link KeyManagerFactory}
850      */
851     public void setSslKeyManagerFactoryAlgorithm(String algorithm)
852     {
853         checkNotStarted();
854 
855         _keyManagerFactoryAlgorithm = algorithm;
856     }
857 
858     /* ------------------------------------------------------------ */
859     /**
860      * @return The algorithm name (default "SunX509") used by the {@link TrustManagerFactory}
861      */
862     public String getTrustManagerFactoryAlgorithm()
863     {
864         return (_trustManagerFactoryAlgorithm);
865     }
866 
867     /* ------------------------------------------------------------ */
868     /**
869      * @param algorithm
870      *            The algorithm name (default "SunX509") used by the {@link TrustManagerFactory}
871      */
872     public void setTrustManagerFactoryAlgorithm(String algorithm)
873     {
874         checkNotStarted();
875 
876         _trustManagerFactoryAlgorithm = algorithm;
877     }
878 
879     /* ------------------------------------------------------------ */
880     /**
881      * @return Path to file that contains Certificate Revocation List
882      */
883     public String getCrlPath()
884     {
885         return _crlPath;
886     }
887 
888     /* ------------------------------------------------------------ */
889     /**
890      * @param crlPath
891      *            Path to file that contains Certificate Revocation List
892      */
893     public void setCrlPath(String crlPath)
894     {
895         checkNotStarted();
896 
897         _crlPath = crlPath;
898     }
899 
900     /* ------------------------------------------------------------ */
901     /**
902      * @return Maximum number of intermediate certificates in
903      * the certification path (-1 for unlimited)
904      */
905     public int getMaxCertPathLength()
906     {
907         return _maxCertPathLength;
908     }
909 
910     /* ------------------------------------------------------------ */
911     /**
912      * @param maxCertPathLength
913      *            maximum number of intermediate certificates in
914      *            the certification path (-1 for unlimited)
915      */
916     public void setMaxCertPathLength(int maxCertPathLength)
917     {
918         checkNotStarted();
919 
920         _maxCertPathLength = maxCertPathLength;
921     }
922 
923     /* ------------------------------------------------------------ */
924     /**
925      * @return The SSLContext
926      */
927     public SSLContext getSslContext()
928     {
929         if (!isStarted())
930             throw new IllegalStateException(getState());
931         return _context;
932     }
933 
934     /* ------------------------------------------------------------ */
935     /**
936      * @param sslContext
937      *            Set a preconfigured SSLContext
938      */
939     public void setSslContext(SSLContext sslContext)
940     {
941         checkNotStarted();
942 
943         _context = sslContext;
944     }
945 
946     /* ------------------------------------------------------------ */
947     /**
948      * Override this method to provide alternate way to load a keystore.
949      *
950      * @return the key store instance
951      * @throws Exception
952      */
953     protected KeyStore loadKeyStore() throws Exception
954     {
955         return _keyStore != null ? _keyStore : getKeyStore(_keyStoreInputStream,
956                 _keyStorePath, _keyStoreType, _keyStoreProvider,
957                 _keyStorePassword==null? null: _keyStorePassword.toString());
958     }
959 
960     /* ------------------------------------------------------------ */
961     /**
962      * Override this method to provide alternate way to load a truststore.
963      *
964      * @return the key store instance
965      * @throws Exception
966      */
967     protected KeyStore loadTrustStore() throws Exception
968     {
969         return _trustStore != null ? _trustStore : getKeyStore(_trustStoreInputStream,
970                 _trustStorePath, _trustStoreType,  _trustStoreProvider,
971                 _trustStorePassword==null? null: _trustStorePassword.toString());
972     }
973 
974     /* ------------------------------------------------------------ */
975     /**
976      * Loads keystore using an input stream or a file path in the same
977      * order of precedence.
978      *
979      * Required for integrations to be able to override the mechanism
980      * used to load a keystore in order to provide their own implementation.
981      *
982      * @param storeStream keystore input stream
983      * @param storePath path of keystore file
984      * @param storeType keystore type
985      * @param storeProvider keystore provider
986      * @param storePassword keystore password
987      * @return created keystore
988      * @throws Exception
989      *
990      * @deprecated
991      */
992     @Deprecated
993     protected KeyStore getKeyStore(InputStream storeStream, String storePath, String storeType, String storeProvider, String storePassword) throws Exception
994     {
995         return CertificateUtils.getKeyStore(storeStream, storePath, storeType, storeProvider, storePassword);
996     }
997 
998     /* ------------------------------------------------------------ */
999     /**
1000      * Loads certificate revocation list (CRL) from a file.
1001      *
1002      * Required for integrations to be able to override the mechanism used to
1003      * load CRL in order to provide their own implementation.
1004      *
1005      * @param crlPath path of certificate revocation list file
1006      * @return Collection of CRL's
1007      * @throws Exception
1008      */
1009     protected Collection<? extends CRL> loadCRL(String crlPath) throws Exception
1010     {
1011         return CertificateUtils.loadCRL(crlPath);
1012     }
1013 
1014     /* ------------------------------------------------------------ */
1015     protected KeyManager[] getKeyManagers(KeyStore keyStore) throws Exception
1016     {
1017         KeyManager[] managers = null;
1018 
1019         if (keyStore != null)
1020         {
1021             KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(_keyManagerFactoryAlgorithm);
1022             keyManagerFactory.init(keyStore,_keyManagerPassword == null?(_keyStorePassword == null?null:_keyStorePassword.toString().toCharArray()):_keyManagerPassword.toString().toCharArray());
1023             managers = keyManagerFactory.getKeyManagers();
1024 
1025             if (_certAlias != null)
1026             {
1027                 for (int idx = 0; idx < managers.length; idx++)
1028                 {
1029                     if (managers[idx] instanceof X509KeyManager)
1030                     {
1031                         managers[idx] = new AliasedX509ExtendedKeyManager(_certAlias,(X509KeyManager)managers[idx]);
1032                     }
1033                 }
1034             }
1035         }
1036 
1037         return managers;
1038     }
1039 
1040     /* ------------------------------------------------------------ */
1041     protected TrustManager[] getTrustManagers(KeyStore trustStore, Collection<? extends CRL> crls) throws Exception
1042     {
1043         TrustManager[] managers = null;
1044         if (trustStore != null)
1045         {
1046             // Revocation checking is only supported for PKIX algorithm
1047             if (_validatePeerCerts && _trustManagerFactoryAlgorithm.equalsIgnoreCase("PKIX"))
1048             {
1049                 PKIXBuilderParameters pbParams = new PKIXBuilderParameters(trustStore,new X509CertSelector());
1050 
1051                 // Set maximum certification path length
1052                 pbParams.setMaxPathLength(_maxCertPathLength);
1053 
1054                 // Make sure revocation checking is enabled
1055                 pbParams.setRevocationEnabled(true);
1056 
1057                 if (crls != null && !crls.isEmpty())
1058                 {
1059                     pbParams.addCertStore(CertStore.getInstance("Collection",new CollectionCertStoreParameters(crls)));
1060                 }
1061 
1062                 if (_enableCRLDP)
1063                 {
1064                     // Enable Certificate Revocation List Distribution Points (CRLDP) support
1065                     System.setProperty("com.sun.security.enableCRLDP","true");
1066                 }
1067 
1068                 if (_enableOCSP)
1069                 {
1070                     // Enable On-Line Certificate Status Protocol (OCSP) support
1071                     Security.setProperty("ocsp.enable","true");
1072 
1073                     if (_ocspResponderURL != null)
1074                     {
1075                         // Override location of OCSP Responder
1076                         Security.setProperty("ocsp.responderURL", _ocspResponderURL);
1077                     }
1078                 }
1079 
1080                 TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerFactoryAlgorithm);
1081                 trustManagerFactory.init(new CertPathTrustManagerParameters(pbParams));
1082 
1083                 managers = trustManagerFactory.getTrustManagers();
1084             }
1085             else
1086             {
1087                 TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerFactoryAlgorithm);
1088                 trustManagerFactory.init(trustStore);
1089 
1090                 managers = trustManagerFactory.getTrustManagers();
1091             }
1092         }
1093 
1094         return managers;
1095     }
1096 
1097     /* ------------------------------------------------------------ */
1098     /**
1099      * Check KetyStore Configuration. Ensures that if keystore has been
1100      * configured but there's no truststore, that keystore is
1101      * used as truststore.
1102      * @throws IllegalStateException if SslContextFactory configuration can't be used.
1103      */
1104     public void checkKeyStore() 
1105     {
1106         if (_keyStore == null && _keyStoreInputStream == null && _keyStorePath == null)
1107             throw new IllegalStateException("SSL doesn't have a valid keystore");
1108         
1109         // if the keystore has been configured but there is no
1110         // truststore configured, use the keystore as the truststore
1111         if (_trustStore == null && _trustStoreInputStream == null && _trustStorePath == null)
1112         {
1113             _trustStore = _keyStore;
1114             _trustStorePath = _keyStorePath;
1115             _trustStoreInputStream = _keyStoreInputStream;
1116             _trustStoreType = _keyStoreType;
1117             _trustStoreProvider = _keyStoreProvider;
1118             _trustStorePassword = _keyStorePassword;
1119             _trustManagerFactoryAlgorithm = _keyManagerFactoryAlgorithm;
1120         }
1121 
1122         // It's the same stream we cannot read it twice, so read it once in memory
1123         if (_keyStoreInputStream != null && _keyStoreInputStream == _trustStoreInputStream)
1124         {
1125             try
1126             {
1127                 ByteArrayOutputStream baos = new ByteArrayOutputStream();
1128                 IO.copy(_keyStoreInputStream, baos);
1129                 _keyStoreInputStream.close();
1130 
1131                 _keyStoreInputStream = new ByteArrayInputStream(baos.toByteArray());
1132                 _trustStoreInputStream = new ByteArrayInputStream(baos.toByteArray());
1133             }
1134             catch (Exception ex)
1135             {
1136                 throw new IllegalStateException(ex);
1137             }
1138         }
1139     }
1140 
1141     /* ------------------------------------------------------------ */
1142     /**
1143      * Select cipher suites to be used by the connector
1144      * based on configured inclusion and exclusion lists
1145      * as well as enabled and supported cipher suite lists.
1146      * @param enabledCipherSuites Array of enabled cipher suites
1147      * @param supportedCipherSuites Array of supported cipher suites
1148      * @return Array of cipher suites to enable
1149      */
1150     public String[] selectProtocols(String[] enabledProtocols, String[] supportedProtocols)
1151     {
1152         Set<String> selected_protocols = new HashSet<String>();
1153         
1154         // Set the starting protocols - either from the included or enabled list
1155         if (_includeProtocols!=null)
1156         {
1157             // Use only the supported included protocols
1158             for (String protocol : supportedProtocols)
1159                 if (_includeProtocols.contains(protocol))
1160                     selected_protocols.add(protocol);
1161         }
1162         else
1163             selected_protocols.addAll(Arrays.asList(enabledProtocols));
1164         
1165         
1166         // Remove any excluded protocols
1167         if (_excludeProtocols != null)
1168             selected_protocols.removeAll(_excludeProtocols);
1169         
1170         return selected_protocols.toArray(new String[selected_protocols.size()]);
1171     }
1172     
1173     /* ------------------------------------------------------------ */
1174     /**
1175      * Select cipher suites to be used by the connector
1176      * based on configured inclusion and exclusion lists
1177      * as well as enabled and supported cipher suite lists.
1178      * @param enabledCipherSuites Array of enabled cipher suites
1179      * @param supportedCipherSuites Array of supported cipher suites
1180      * @return Array of cipher suites to enable
1181      */
1182     public String[] selectCipherSuites(String[] enabledCipherSuites, String[] supportedCipherSuites)
1183     {
1184         Set<String> selected_ciphers = new HashSet<String>();
1185         
1186         // Set the starting ciphers - either from the included or enabled list
1187         if (_includeCipherSuites!=null)
1188         {
1189             // Use only the supported included ciphers
1190             for (String cipherSuite : supportedCipherSuites)
1191                 if (_includeCipherSuites.contains(cipherSuite))
1192                     selected_ciphers.add(cipherSuite);
1193         }
1194         else
1195             selected_ciphers.addAll(Arrays.asList(enabledCipherSuites));
1196         
1197         
1198         // Remove any excluded ciphers
1199         if (_excludeCipherSuites != null)
1200             selected_ciphers.removeAll(_excludeCipherSuites);
1201         return selected_ciphers.toArray(new String[selected_ciphers.size()]);
1202     }
1203 
1204     /* ------------------------------------------------------------ */
1205     /**
1206      * Check if the lifecycle has been started and throw runtime exception
1207      */
1208     protected void checkNotStarted()
1209     {
1210         if (isStarted())
1211             throw new IllegalStateException("Cannot modify configuration when "+getState());
1212     }
1213 
1214     /* ------------------------------------------------------------ */
1215     /**
1216      * @return true if CRL Distribution Points support is enabled
1217      */
1218     public boolean isEnableCRLDP()
1219     {
1220         return _enableCRLDP;
1221     }
1222 
1223     /* ------------------------------------------------------------ */
1224     /** Enables CRL Distribution Points Support
1225      * @param enableCRLDP true - turn on, false - turns off
1226      */
1227     public void setEnableCRLDP(boolean enableCRLDP)
1228     {
1229         checkNotStarted();
1230 
1231         _enableCRLDP = enableCRLDP;
1232     }
1233 
1234     /* ------------------------------------------------------------ */
1235     /**
1236      * @return true if On-Line Certificate Status Protocol support is enabled
1237      */
1238     public boolean isEnableOCSP()
1239     {
1240         return _enableOCSP;
1241     }
1242 
1243     /* ------------------------------------------------------------ */
1244     /** Enables On-Line Certificate Status Protocol support
1245      * @param enableOCSP true - turn on, false - turn off
1246      */
1247     public void setEnableOCSP(boolean enableOCSP)
1248     {
1249         checkNotStarted();
1250 
1251         _enableOCSP = enableOCSP;
1252     }
1253 
1254     /* ------------------------------------------------------------ */
1255     /**
1256      * @return Location of the OCSP Responder
1257      */
1258     public String getOcspResponderURL()
1259     {
1260         return _ocspResponderURL;
1261     }
1262 
1263     /* ------------------------------------------------------------ */
1264     /** Set the location of the OCSP Responder.
1265      * @param ocspResponderURL location of the OCSP Responder
1266      */
1267     public void setOcspResponderURL(String ocspResponderURL)
1268     {
1269         checkNotStarted();
1270 
1271         _ocspResponderURL = ocspResponderURL;
1272     }
1273 
1274     /* ------------------------------------------------------------ */
1275     /** Set the key store.
1276      * @param keyStore the key store to set
1277      */
1278     public void setKeyStore(KeyStore keyStore)
1279     {
1280         checkNotStarted();
1281 
1282         _keyStore = keyStore;
1283     }
1284 
1285     /* ------------------------------------------------------------ */
1286     /** Set the trust store.
1287      * @param trustStore the trust store to set
1288      */
1289     public void setTrustStore(KeyStore trustStore)
1290     {
1291         checkNotStarted();
1292 
1293         _trustStore = trustStore;
1294     }
1295 
1296     /* ------------------------------------------------------------ */
1297     /** Set the key store resource.
1298      * @param resource the key store resource to set
1299      */
1300     public void setKeyStoreResource(Resource resource)
1301     {
1302         checkNotStarted();
1303 
1304         try
1305         {
1306             _keyStoreInputStream = resource.getInputStream();
1307         }
1308         catch (IOException e)
1309         {
1310              throw new InvalidParameterException("Unable to get resource "+
1311                      "input stream for resource "+resource.toString());
1312         }
1313     }
1314 
1315     /* ------------------------------------------------------------ */
1316     /** Set the trust store resource.
1317      * @param resource the trust store resource to set
1318      */
1319     public void setTrustStore(Resource resource)
1320     {
1321         checkNotStarted();
1322 
1323         try
1324         {
1325             _trustStoreInputStream = resource.getInputStream();
1326         }
1327         catch (IOException e)
1328         {
1329              throw new InvalidParameterException("Unable to get resource "+
1330                      "input stream for resource "+resource.toString());
1331         }
1332     }
1333 
1334     /* ------------------------------------------------------------ */
1335     /**
1336     * @return true if SSL Session caching is enabled
1337     */
1338     public boolean isSessionCachingEnabled()
1339     {
1340         return _sessionCachingEnabled;
1341     }
1342 
1343     /* ------------------------------------------------------------ */
1344     /** Set the flag to enable SSL Session caching.
1345     * @param enableSessionCaching the value of the flag
1346     */
1347     public void setSessionCachingEnabled(boolean enableSessionCaching)
1348     {
1349         _sessionCachingEnabled = enableSessionCaching;
1350     }
1351 
1352     /* ------------------------------------------------------------ */
1353     /** Get SSL session cache size.
1354      * @return SSL session cache size
1355      */
1356     public int getSslSessionCacheSize()
1357     {
1358         return _sslSessionCacheSize;
1359     }
1360 
1361     /* ------------------------------------------------------------ */
1362     /** SEt SSL session cache size.
1363      * @param sslSessionCacheSize SSL session cache size to set
1364      */
1365     public void setSslSessionCacheSize(int sslSessionCacheSize)
1366     {
1367         _sslSessionCacheSize = sslSessionCacheSize;
1368     }
1369 
1370     /* ------------------------------------------------------------ */
1371     /** Get SSL session timeout.
1372      * @return SSL session timeout
1373      */
1374     public int getSslSessionTimeout()
1375     {
1376         return _sslSessionTimeout;
1377     }
1378 
1379     /* ------------------------------------------------------------ */
1380     /** Set SSL session timeout.
1381      * @param sslSessionTimeout SSL session timeout to set
1382      */
1383     public void setSslSessionTimeout(int sslSessionTimeout)
1384     {
1385         _sslSessionTimeout = sslSessionTimeout;
1386     }
1387 
1388 
1389     /* ------------------------------------------------------------ */
1390     public SSLServerSocket newSslServerSocket(String host,int port,int backlog) throws IOException
1391     {
1392         SSLServerSocketFactory factory = _context.getServerSocketFactory();
1393 
1394         SSLServerSocket socket = 
1395             (SSLServerSocket) (host==null ?
1396                         factory.createServerSocket(port,backlog):
1397                         factory.createServerSocket(port,backlog,InetAddress.getByName(host)));
1398 
1399         if (getWantClientAuth())
1400             socket.setWantClientAuth(getWantClientAuth());
1401         if (getNeedClientAuth())
1402             socket.setNeedClientAuth(getNeedClientAuth());
1403 
1404         socket.setEnabledCipherSuites(selectCipherSuites(
1405                                             socket.getEnabledCipherSuites(),
1406                                             socket.getSupportedCipherSuites()));
1407         socket.setEnabledProtocols(selectProtocols(socket.getEnabledProtocols(),socket.getSupportedProtocols()));
1408 
1409         return socket;
1410     }
1411     
1412     /* ------------------------------------------------------------ */
1413     public SSLSocket newSslSocket() throws IOException
1414     {
1415         SSLSocketFactory factory = _context.getSocketFactory();
1416         
1417         SSLSocket socket = (SSLSocket)factory.createSocket();
1418         
1419         if (getWantClientAuth())
1420             socket.setWantClientAuth(getWantClientAuth());
1421         if (getNeedClientAuth())
1422             socket.setNeedClientAuth(getNeedClientAuth());
1423 
1424         socket.setEnabledCipherSuites(selectCipherSuites(
1425                                             socket.getEnabledCipherSuites(),
1426                                             socket.getSupportedCipherSuites()));   
1427         socket.setEnabledProtocols(selectProtocols(socket.getEnabledProtocols(),socket.getSupportedProtocols()));
1428 
1429         return socket;
1430     }
1431     
1432     /* ------------------------------------------------------------ */
1433     public SSLEngine newSslEngine(String host,int port)
1434     {
1435         SSLEngine sslEngine=isSessionCachingEnabled()
1436             ?_context.createSSLEngine(host, port)
1437             :_context.createSSLEngine();
1438             
1439         customize(sslEngine);
1440         return sslEngine;
1441     }
1442     
1443     /* ------------------------------------------------------------ */
1444     public SSLEngine newSslEngine()
1445     {
1446         SSLEngine sslEngine=_context.createSSLEngine();
1447         customize(sslEngine);
1448         return sslEngine;
1449     }
1450 
1451     /* ------------------------------------------------------------ */
1452     public void customize(SSLEngine sslEngine)
1453     {
1454         if (getWantClientAuth())
1455             sslEngine.setWantClientAuth(getWantClientAuth());
1456         if (getNeedClientAuth())
1457             sslEngine.setNeedClientAuth(getNeedClientAuth());
1458 
1459         sslEngine.setEnabledCipherSuites(selectCipherSuites(
1460                 sslEngine.getEnabledCipherSuites(),
1461                 sslEngine.getSupportedCipherSuites()));
1462         
1463         sslEngine.setEnabledProtocols(selectProtocols(sslEngine.getEnabledProtocols(),sslEngine.getSupportedProtocols()));
1464     }
1465     
1466 }