1
2
3
4
5
6
7
8
9
10
11
12
13
14
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.InputStream;
23 import java.security.KeyStore;
24 import java.security.SecureRandom;
25 import java.security.Security;
26 import java.security.cert.CRL;
27 import java.security.cert.CertStore;
28 import java.security.cert.Certificate;
29 import java.security.cert.CollectionCertStoreParameters;
30 import java.security.cert.PKIXBuilderParameters;
31 import java.security.cert.X509CertSelector;
32 import java.util.Arrays;
33 import java.util.Collection;
34 import java.util.Collections;
35 import java.util.HashSet;
36 import java.util.List;
37 import java.util.Set;
38
39 import javax.net.ssl.CertPathTrustManagerParameters;
40 import javax.net.ssl.KeyManager;
41 import javax.net.ssl.KeyManagerFactory;
42 import javax.net.ssl.SSLContext;
43 import javax.net.ssl.SSLEngine;
44 import javax.net.ssl.TrustManager;
45 import javax.net.ssl.TrustManagerFactory;
46 import javax.net.ssl.X509KeyManager;
47 import javax.net.ssl.X509TrustManager;
48
49 import org.eclipse.jetty.http.security.Password;
50 import org.eclipse.jetty.util.IO;
51 import org.eclipse.jetty.util.component.AbstractLifeCycle;
52 import org.eclipse.jetty.util.security.CertificateUtils;
53 import org.eclipse.jetty.util.security.CertificateValidator;
54
55
56
57
58
59
60
61
62
63 public class SslContextFactory extends AbstractLifeCycle
64 {
65 public static final String DEFAULT_KEYMANAGERFACTORY_ALGORITHM =
66 (Security.getProperty("ssl.KeyManagerFactory.algorithm") == null ?
67 "SunX509" : Security.getProperty("ssl.KeyManagerFactory.algorithm"));
68 public static final String DEFAULT_TRUSTMANAGERFACTORY_ALGORITHM =
69 (Security.getProperty("ssl.TrustManagerFactory.algorithm") == null ?
70 "SunX509" : Security.getProperty("ssl.TrustManagerFactory.algorithm"));
71
72
73 public static final String DEFAULT_KEYSTORE_PATH =
74 System.getProperty("user.home") + File.separator + ".keystore";
75
76
77 public static final String KEYPASSWORD_PROPERTY = "org.eclipse.jetty.ssl.keypassword";
78
79
80 public static final String PASSWORD_PROPERTY = "org.eclipse.jetty.ssl.password";
81
82
83 private Set<String> _excludeCipherSuites = null;
84
85 private Set<String> _includeCipherSuites = null;
86
87
88 private String _keyStorePath;
89
90 private String _keyStoreProvider;
91
92 private String _keyStoreType = "JKS";
93
94 private InputStream _keyStoreInputStream;
95
96
97 private String _certAlias;
98
99
100 private String _trustStorePath;
101
102 private String _trustStoreProvider;
103
104 private String _trustStoreType = "JKS";
105
106 private InputStream _trustStoreInputStream;
107
108
109 private boolean _needClientAuth = false;
110
111 private boolean _wantClientAuth = false;
112
113
114 private boolean _allowRenegotiate = true;
115
116
117 private transient Password _keyStorePassword;
118
119 private transient Password _keyManagerPassword;
120
121 private transient Password _trustStorePassword;
122
123
124 private String _sslProvider;
125
126 private String _sslProtocol = "TLS";
127
128
129 private String _secureRandomAlgorithm;
130
131 private String _keyManagerFactoryAlgorithm = DEFAULT_KEYMANAGERFACTORY_ALGORITHM;
132
133 private String _trustManagerFactoryAlgorithm = DEFAULT_TRUSTMANAGERFACTORY_ALGORITHM;
134
135
136 private boolean _validateCerts;
137
138 private int _maxCertPathLength = -1;
139
140 private String _crlPath;
141
142 private boolean _enableCRLDP = false;
143
144 private boolean _enableOCSP = false;
145
146 private String _ocspResponderURL;
147
148
149 private SSLContext _context;
150
151
152
153
154
155
156 public SslContextFactory()
157 {
158 }
159
160
161
162
163
164
165 public SslContextFactory(String keyStorePath)
166 {
167 _keyStorePath = keyStorePath;
168 }
169
170
171
172
173
174
175 @Override
176 protected void doStart() throws Exception
177 {
178 if (_context == null)
179 {
180 if (_keyStoreInputStream == null && _keyStorePath == null &&
181 _trustStoreInputStream == null && _trustStorePath == null )
182 {
183
184 TrustManager trustAllCerts = new X509TrustManager()
185 {
186 public java.security.cert.X509Certificate[] getAcceptedIssuers()
187 {
188 return null;
189 }
190
191 public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
192 {
193 }
194
195 public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
196 {
197 }
198 };
199
200 _context = SSLContext.getInstance(_sslProtocol);
201 _context.init(null, new TrustManager[]{trustAllCerts}, null);
202 }
203 else
204 {
205 createSSLContext();
206 }
207 }
208 }
209
210
211
212
213
214
215 public String[] getExcludeCipherSuites()
216 {
217 return _excludeCipherSuites.toArray(new String[_excludeCipherSuites.size()]);
218 }
219
220
221
222
223
224
225
226 public void setExcludeCipherSuites(String[] cipherSuites)
227 {
228 checkStarted();
229
230 _excludeCipherSuites = new HashSet<String>(Arrays.asList(cipherSuites));
231 }
232
233
234
235
236
237
238 public String[] getIncludeCipherSuites()
239 {
240 return _includeCipherSuites.toArray(new String[_includeCipherSuites.size()]);
241 }
242
243
244
245
246
247
248
249 public void setIncludeCipherSuites(String[] cipherSuites)
250 {
251 checkStarted();
252
253 _includeCipherSuites = new HashSet<String>(Arrays.asList(cipherSuites));
254 }
255
256
257
258
259
260 public String getKeyStore()
261 {
262 return _keyStorePath;
263 }
264
265
266
267
268
269
270 public void setKeyStore(String keyStorePath)
271 {
272 checkStarted();
273
274 _keyStorePath = keyStorePath;
275 }
276
277
278
279
280
281 public String getKeyStoreProvider()
282 {
283 return _keyStoreProvider;
284 }
285
286
287
288
289
290
291 public void setKeyStoreProvider(String keyStoreProvider)
292 {
293 checkStarted();
294
295 _keyStoreProvider = keyStoreProvider;
296 }
297
298
299
300
301
302 public String getKeyStoreType()
303 {
304 return (_keyStoreType);
305 }
306
307
308
309
310
311
312 public void setKeyStoreType(String keyStoreType)
313 {
314 checkStarted();
315
316 _keyStoreType = keyStoreType;
317 }
318
319
320
321
322
323 public InputStream getKeyStoreInputStream()
324 {
325 checkConfig();
326
327 return _keyStoreInputStream;
328 }
329
330
331
332
333
334 public void setKeyStoreInputStream(InputStream keyStoreInputStream)
335 {
336 checkStarted();
337
338 _keyStoreInputStream = keyStoreInputStream;
339 }
340
341
342
343
344
345 public String getCertAlias()
346 {
347 return _certAlias;
348 }
349
350
351
352
353
354
355 public void setCertAlias(String certAlias)
356 {
357 checkStarted();
358
359 _certAlias = certAlias;
360 }
361
362
363
364
365
366 public String getTrustStore()
367 {
368 return _trustStorePath;
369 }
370
371
372
373
374
375
376 public void setTrustStore(String trustStorePath)
377 {
378 checkStarted();
379
380 _trustStorePath = trustStorePath;
381 }
382
383
384
385
386
387 public String getTrustStoreProvider()
388 {
389 return _trustStoreProvider;
390 }
391
392
393
394
395
396
397 public void setTrustStoreProvider(String trustStoreProvider)
398 {
399 checkStarted();
400
401 _trustStoreProvider = trustStoreProvider;
402 }
403
404
405
406
407
408 public String getTrustStoreType()
409 {
410 return _trustStoreType;
411 }
412
413
414
415
416
417
418 public void setTrustStoreType(String trustStoreType)
419 {
420 checkStarted();
421
422 _trustStoreType = trustStoreType;
423 }
424
425
426
427
428
429 public InputStream getTrustStoreInputStream()
430 {
431 checkConfig();
432
433 return _trustStoreInputStream;
434 }
435
436
437
438
439
440 public void setTrustStoreInputStream(InputStream trustStoreInputStream)
441 {
442 checkStarted();
443
444 _trustStoreInputStream = trustStoreInputStream;
445 }
446
447
448
449
450
451
452 public boolean getNeedClientAuth()
453 {
454 return _needClientAuth;
455 }
456
457
458
459
460
461
462
463 public void setNeedClientAuth(boolean needClientAuth)
464 {
465 checkStarted();
466
467 _needClientAuth = needClientAuth;
468 }
469
470
471
472
473
474
475 public boolean getWantClientAuth()
476 {
477 return _wantClientAuth;
478 }
479
480
481
482
483
484
485
486 public void setWantClientAuth(boolean wantClientAuth)
487 {
488 checkStarted();
489
490 _wantClientAuth = wantClientAuth;
491 }
492
493
494
495
496
497
498 @Deprecated
499 public boolean getValidateCerts()
500 {
501 return _validateCerts;
502 }
503
504
505
506
507
508 public boolean isValidateCerts()
509 {
510 return _validateCerts;
511 }
512
513
514
515
516
517
518 public void setValidateCerts(boolean validateCerts)
519 {
520 checkStarted();
521
522 _validateCerts = validateCerts;
523 }
524
525
526
527
528
529 public boolean isAllowRenegotiate()
530 {
531 return _allowRenegotiate;
532 }
533
534
535
536
537
538
539
540
541
542
543
544
545 public void setAllowRenegotiate(boolean allowRenegotiate)
546 {
547 checkStarted();
548
549 _allowRenegotiate = allowRenegotiate;
550 }
551
552
553
554
555
556
557 public void setKeyStorePassword(String password)
558 {
559 checkStarted();
560
561 _keyStorePassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
562 }
563
564
565
566
567
568
569 public void setKeyManagerPassword(String password)
570 {
571 checkStarted();
572
573 _keyManagerPassword = Password.getPassword(KEYPASSWORD_PROPERTY,password,null);
574 }
575
576
577
578
579
580
581 public void setTrustStorePassword(String password)
582 {
583 checkStarted();
584
585 _trustStorePassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
586 }
587
588
589
590
591
592
593 public String getProvider()
594 {
595 return _sslProvider;
596 }
597
598
599
600
601
602
603
604 public void setProvider(String provider)
605 {
606 checkStarted();
607
608 _sslProvider = provider;
609 }
610
611
612
613
614
615
616 public String getProtocol()
617 {
618 return _sslProtocol;
619 }
620
621
622
623
624
625
626
627 public void setProtocol(String protocol)
628 {
629 checkStarted();
630
631 _sslProtocol = protocol;
632 }
633
634
635
636
637
638
639
640 public String getSecureRandomAlgorithm()
641 {
642 return _secureRandomAlgorithm;
643 }
644
645
646
647
648
649
650
651
652 public void setSecureRandomAlgorithm(String algorithm)
653 {
654 checkStarted();
655
656 _secureRandomAlgorithm = algorithm;
657 }
658
659
660
661
662
663 public String getSslKeyManagerFactoryAlgorithm()
664 {
665 return (_keyManagerFactoryAlgorithm);
666 }
667
668
669
670
671
672
673 public void setSslKeyManagerFactoryAlgorithm(String algorithm)
674 {
675 checkStarted();
676
677 _keyManagerFactoryAlgorithm = algorithm;
678 }
679
680
681
682
683
684 public String getTrustManagerFactoryAlgorithm()
685 {
686 return (_trustManagerFactoryAlgorithm);
687 }
688
689
690
691
692
693
694 public void setTrustManagerFactoryAlgorithm(String algorithm)
695 {
696 checkStarted();
697
698 _trustManagerFactoryAlgorithm = algorithm;
699 }
700
701
702
703
704
705 public String getCrlPath()
706 {
707 return _crlPath;
708 }
709
710
711
712
713
714
715 public void setCrlPath(String crlPath)
716 {
717 checkStarted();
718
719 _crlPath = crlPath;
720 }
721
722
723
724
725
726
727 public int getMaxCertPathLength()
728 {
729 return _maxCertPathLength;
730 }
731
732
733
734
735
736
737
738 public void setMaxCertPathLength(int maxCertPathLength)
739 {
740 checkStarted();
741
742 _maxCertPathLength = maxCertPathLength;
743 }
744
745
746
747
748
749 public SSLContext getSslContext()
750 {
751 return _context;
752 }
753
754
755
756
757
758
759 public void setSslContext(SSLContext sslContext)
760 {
761 checkStarted();
762
763 _context = sslContext;
764 }
765
766
767
768
769
770 protected void createSSLContext() throws Exception
771 {
772
773
774 checkConfig();
775
776 KeyStore keyStore = getKeyStore(_keyStoreInputStream, _keyStorePath, _keyStoreType,
777 _keyStoreProvider, _keyStorePassword==null? null: _keyStorePassword.toString());
778 KeyStore trustStore = getKeyStore(_trustStoreInputStream, _trustStorePath, _trustStoreType,
779 _trustStoreProvider, _trustStorePassword==null? null: _trustStorePassword.toString());
780 Collection<? extends CRL> crls = loadCRL(_crlPath);
781
782 if (_validateCerts && keyStore != null)
783 {
784 if (_certAlias == null)
785 {
786 List<String> aliases = Collections.list(keyStore.aliases());
787 _certAlias = aliases.size() == 1 ? aliases.get(0) : null;
788 }
789
790 Certificate cert = _certAlias == null?null:keyStore.getCertificate(_certAlias);
791 if (cert == null)
792 {
793 throw new Exception("No certificate found in the keystore" + (_certAlias==null ? "":" for alias " + _certAlias));
794 }
795
796 CertificateValidator validator = new CertificateValidator(trustStore, crls);
797 validator.setMaxCertPathLength(_maxCertPathLength);
798 validator.setEnableCRLDP(_enableCRLDP);
799 validator.setEnableOCSP(_enableOCSP);
800 validator.setOcspResponderURL(_ocspResponderURL);
801 validator.validate(keyStore, cert);
802 }
803
804 KeyManager[] keyManagers = getKeyManagers(keyStore);
805 TrustManager[] trustManagers = getTrustManagers(trustStore,crls);
806
807 SecureRandom secureRandom = _secureRandomAlgorithm == null?null:SecureRandom.getInstance(_secureRandomAlgorithm);
808 _context = _sslProvider == null?SSLContext.getInstance(_sslProtocol):SSLContext.getInstance(_sslProtocol,_sslProvider);
809 _context.init(keyManagers,trustManagers,secureRandom);
810 }
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828 protected KeyStore getKeyStore(InputStream storeStream, String storePath, String storeType, String storeProvider, String storePassword) throws Exception
829 {
830 return CertificateUtils.getKeyStore(storeStream, storePath, storeType, storeProvider, storePassword);
831 }
832
833
834
835
836
837
838
839
840
841
842
843
844 protected Collection<? extends CRL> loadCRL(String crlPath) throws Exception
845 {
846 return CertificateUtils.loadCRL(crlPath);
847 }
848
849
850 protected KeyManager[] getKeyManagers(KeyStore keyStore) throws Exception
851 {
852 KeyManager[] managers = null;
853
854 if (keyStore != null)
855 {
856 KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(_keyManagerFactoryAlgorithm);
857 keyManagerFactory.init(keyStore,_keyManagerPassword == null?(_keyStorePassword == null?null:_keyStorePassword.toString().toCharArray()):_keyManagerPassword.toString().toCharArray());
858 managers = keyManagerFactory.getKeyManagers();
859
860 if (_certAlias != null)
861 {
862 for (int idx = 0; idx < managers.length; idx++)
863 {
864 if (managers[idx] instanceof X509KeyManager)
865 {
866 managers[idx] = new AliasedX509ExtendedKeyManager(_certAlias,(X509KeyManager)managers[idx]);
867 }
868 }
869 }
870 }
871
872 return managers;
873 }
874
875
876 protected TrustManager[] getTrustManagers(KeyStore trustStore, Collection<? extends CRL> crls) throws Exception
877 {
878 TrustManager[] managers = null;
879 if (trustStore != null)
880 {
881
882 if (_validateCerts && _trustManagerFactoryAlgorithm.equalsIgnoreCase("PKIX"))
883 {
884 PKIXBuilderParameters pbParams = new PKIXBuilderParameters(trustStore,new X509CertSelector());
885
886
887 pbParams.setMaxPathLength(_maxCertPathLength);
888
889
890 pbParams.setRevocationEnabled(true);
891
892 if (crls != null && !crls.isEmpty())
893 {
894 pbParams.addCertStore(CertStore.getInstance("Collection",new CollectionCertStoreParameters(crls)));
895 }
896
897 if (_enableCRLDP)
898 {
899
900 System.setProperty("com.sun.security.enableCRLDP","true");
901 }
902
903 if (_enableOCSP)
904 {
905
906 Security.setProperty("ocsp.enable","true");
907
908 if (_ocspResponderURL != null)
909 {
910
911 Security.setProperty("ocsp.responderURL", _ocspResponderURL);
912 }
913 }
914
915 TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerFactoryAlgorithm);
916 trustManagerFactory.init(new CertPathTrustManagerParameters(pbParams));
917
918 managers = trustManagerFactory.getTrustManagers();
919 }
920 else
921 {
922 TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerFactoryAlgorithm);
923 trustManagerFactory.init(trustStore);
924
925 managers = trustManagerFactory.getTrustManagers();
926 }
927 }
928
929 return managers;
930 }
931
932
933
934
935
936
937
938
939 public boolean checkConfig()
940 {
941 boolean check = true;
942 if (_keyStoreInputStream == null && _keyStorePath == null)
943 {
944
945 check = false;
946 }
947 else
948 {
949
950
951 if (_trustStoreInputStream == null && _trustStorePath == null)
952 {
953 _trustStorePath = _keyStorePath;
954 _trustStoreInputStream = _keyStoreInputStream;
955 _trustStoreType = _keyStoreType;
956 _trustStoreProvider = _keyStoreProvider;
957 _trustStorePassword = _keyStorePassword;
958 _trustManagerFactoryAlgorithm = _keyManagerFactoryAlgorithm;
959 }
960 }
961
962
963 if (_keyStoreInputStream != null && _keyStoreInputStream == _trustStoreInputStream)
964 {
965 try
966 {
967 ByteArrayOutputStream baos = new ByteArrayOutputStream();
968 IO.copy(_keyStoreInputStream, baos);
969 _keyStoreInputStream.close();
970
971 _keyStoreInputStream = new ByteArrayInputStream(baos.toByteArray());
972 _trustStoreInputStream = new ByteArrayInputStream(baos.toByteArray());
973 }
974 catch (Exception ex)
975 {
976 throw new RuntimeException(ex);
977 }
978 }
979
980 return check;
981 }
982
983
984
985
986
987
988
989
990
991
992 public String[] selectCipherSuites(String[] enabledCipherSuites, String[] supportedCipherSuites)
993 {
994 Set<String> selectedCipherSuites = null;
995 if (enabledCipherSuites != null)
996 {
997 selectedCipherSuites = new HashSet<String>(Arrays.asList(enabledCipherSuites));
998 }
999 else
1000 {
1001 selectedCipherSuites = new HashSet<String>();
1002 }
1003
1004 if ((supportedCipherSuites != null && supportedCipherSuites.length > 0) &&
1005 (_includeCipherSuites != null && _includeCipherSuites.size() > 0))
1006 {
1007 Set<String> supportedCSList = new HashSet<String>(Arrays.asList(supportedCipherSuites));
1008
1009 for (String cipherName : _includeCipherSuites)
1010 {
1011 if ((!selectedCipherSuites.contains(cipherName)) &&
1012 supportedCSList.contains(cipherName))
1013 {
1014 selectedCipherSuites.add(cipherName);
1015 }
1016 }
1017 }
1018
1019 if (_excludeCipherSuites != null && _excludeCipherSuites.size() > 0)
1020 {
1021 for (String cipherName : _excludeCipherSuites)
1022 {
1023 if (selectedCipherSuites.contains(cipherName))
1024 {
1025 selectedCipherSuites.remove(cipherName);
1026 }
1027 }
1028 }
1029
1030 return selectedCipherSuites.toArray(new String[selectedCipherSuites.size()]);
1031 }
1032
1033
1034
1035
1036
1037 protected void checkStarted()
1038 {
1039 if (isStarted())
1040 {
1041 throw new IllegalStateException("Cannot modify configuration after SslContextFactory was started");
1042 }
1043 }
1044
1045
1046
1047
1048
1049 public boolean isEnableCRLDP()
1050 {
1051 return _enableCRLDP;
1052 }
1053
1054
1055
1056
1057
1058 public void setEnableCRLDP(boolean enableCRLDP)
1059 {
1060 _enableCRLDP = enableCRLDP;
1061 }
1062
1063
1064
1065
1066
1067 public boolean isEnableOCSP()
1068 {
1069 return _enableOCSP;
1070 }
1071
1072
1073
1074
1075
1076 public void setEnableOCSP(boolean enableOCSP)
1077 {
1078 _enableOCSP = enableOCSP;
1079 }
1080
1081
1082
1083
1084
1085 public String getOcspResponderURL()
1086 {
1087 return _ocspResponderURL;
1088 }
1089
1090
1091
1092
1093
1094 public void setOcspResponderURL(String ocspResponderURL)
1095 {
1096 _ocspResponderURL = ocspResponderURL;
1097 }
1098 }