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