1919import javax .net .ssl .CertPathTrustManagerParameters ;
2020import javax .net .ssl .KeyManager ;
2121import javax .net .ssl .KeyManagerFactory ;
22+ import javax .net .ssl .ManagerFactoryParameters ;
2223import javax .net .ssl .SSLContext ;
2324import javax .net .ssl .TrustManager ;
2425import javax .net .ssl .TrustManagerFactory ;
3738import java .security .Security ;
3839import java .security .UnrecoverableKeyException ;
3940import java .security .cert .CRL ;
41+ import java .security .cert .CertPathBuilder ;
42+ import java .security .cert .CertPathValidatorException ;
4043import java .security .cert .CertStore ;
4144import java .security .cert .Certificate ;
4245import java .security .cert .CertificateFactory ;
4346import java .security .cert .CollectionCertStoreParameters ;
4447import java .security .cert .PKIXBuilderParameters ;
48+ import java .security .cert .PKIXCertPathChecker ;
49+ import java .security .cert .PKIXRevocationChecker ;
4550import java .security .cert .X509CertSelector ;
4651import java .security .cert .X509Certificate ;
4752import java .util .Collection ;
53+ import java .util .HashSet ;
54+ import java .util .List ;
55+ import java .util .Set ;
4856
4957import io .netty .handler .ssl .SslContext ;
5058import io .netty .handler .ssl .SslContextBuilder ;
@@ -81,6 +89,8 @@ public class SSLSupport {
8189 private boolean trustAll = TransportConstants .DEFAULT_TRUST_ALL ;
8290 private String trustManagerFactoryPlugin = TransportConstants .DEFAULT_TRUST_MANAGER_FACTORY_PLUGIN ;
8391 private String keystoreAlias = TransportConstants .DEFAULT_KEYSTORE_ALIAS ;
92+ private String crcOptions = TransportConstants .DEFAULT_CRC_OPTIONS ;
93+ private String ocspResponderURL = TransportConstants .DEFAULT_OCSP_RESPONDER_URL ;
8494
8595 public SSLSupport () {
8696 }
@@ -98,6 +108,8 @@ public SSLSupport(final SSLContextConfig config) {
98108 trustAll = config .isTrustAll ();
99109 trustManagerFactoryPlugin = config .getTrustManagerFactoryPlugin ();
100110 keystoreAlias = config .getKeystoreAlias ();
111+ crcOptions = config .getCrcOptions ();
112+ ocspResponderURL = config .getOcspResponderURL ();
101113 }
102114
103115 public String getKeystoreProvider () {
@@ -217,6 +229,24 @@ public SSLSupport setTrustManagerFactoryPlugin(String trustManagerFactoryPlugin)
217229 return this ;
218230 }
219231
232+ public String getCrcOptions () {
233+ return crcOptions ;
234+ }
235+
236+ public SSLSupport setCrcOptions (String crcOptions ) {
237+ this .crcOptions = crcOptions ;
238+ return this ;
239+ }
240+
241+ public String getOcspResponderURL () {
242+ return ocspResponderURL ;
243+ }
244+
245+ public SSLSupport setOcspResponderURL (String ocspResponderURL ) {
246+ this .ocspResponderURL = ocspResponderURL ;
247+ return this ;
248+ }
249+
220250 public SSLContext createContext () throws Exception {
221251 SSLContext context = SSLContext .getInstance ("TLS" );
222252 KeyManager [] keyManagers = loadKeyManagers ();
@@ -287,29 +317,122 @@ private TrustManagerFactory loadTrustManagerFactory() throws Exception {
287317 } else {
288318 TrustManagerFactory trustMgrFactory = TrustManagerFactory .getInstance (TrustManagerFactory .getDefaultAlgorithm ());
289319 KeyStore trustStore = SSLSupport .loadKeystore (truststoreProvider , truststoreType , truststorePath , truststorePassword );
290- boolean ocsp = Boolean .valueOf (Security .getProperty ("ocsp.enable" ));
291320
292- boolean initialized = false ;
293- if ((ocsp || crlPath != null ) && TrustManagerFactory .getDefaultAlgorithm ().equalsIgnoreCase ("PKIX" )) {
321+ ManagerFactoryParameters managerFactoryParameters = null ;
322+ boolean ocsp = Boolean .parseBoolean (Security .getProperty ("ocsp.enable" ));
323+ if ((ocsp || crlPath != null || crcOptions != null || ocspResponderURL != null ) && checkPKIXTrustManagerFactory (trustMgrFactory )) {
294324 PKIXBuilderParameters pkixParams = new PKIXBuilderParameters (trustStore , new X509CertSelector ());
325+
295326 if (crlPath != null ) {
296327 pkixParams .setRevocationEnabled (true );
297328 Collection <? extends CRL > crlList = loadCRL ();
298329 if (crlList != null ) {
299330 pkixParams .addCertStore (CertStore .getInstance ("Collection" , new CollectionCertStoreParameters (crlList )));
300331 }
301332 }
302- trustMgrFactory .init (new CertPathTrustManagerParameters (pkixParams ));
303- initialized = true ;
333+
334+ if (crcOptions != null || ocspResponderURL != null ) {
335+ addCertPathCheckers (pkixParams );
336+ }
337+
338+ managerFactoryParameters = new CertPathTrustManagerParameters (pkixParams );
304339 }
305340
306- if (!initialized ) {
341+ if (managerFactoryParameters != null ) {
342+ trustMgrFactory .init (managerFactoryParameters );
343+ } else {
307344 trustMgrFactory .init (trustStore );
308345 }
346+
309347 return trustMgrFactory ;
310348 }
311349 }
312350
351+ private boolean checkPKIXTrustManagerFactory (TrustManagerFactory trustMgrFactory ) {
352+ if (trustMgrFactory .getAlgorithm ().equalsIgnoreCase ("PKIX" )) {
353+ return true ;
354+ }
355+
356+ if (crlPath != null ) {
357+ throw new IllegalStateException ("The crlPath parameter is not supported with the algorithm "
358+ + trustMgrFactory .getAlgorithm ());
359+ }
360+
361+ if (crcOptions != null ) {
362+ throw new IllegalStateException ("The crcOptions parameter is not supported with the algorithm "
363+ + trustMgrFactory .getAlgorithm ());
364+ }
365+
366+ if (ocspResponderURL != null ) {
367+ throw new IllegalStateException ("The ocspResponderURL parameter is not supported with the algorithm "
368+ + trustMgrFactory .getAlgorithm ());
369+ }
370+
371+ return false ;
372+ }
373+
374+ protected void addCertPathCheckers (PKIXBuilderParameters pkixParams ) throws Exception {
375+ CertPathBuilder certPathBuilder = CertPathBuilder .getInstance ("PKIX" );
376+ PKIXRevocationChecker revocationChecker = (PKIXRevocationChecker ) certPathBuilder .getRevocationChecker ();
377+ if (crcOptions != null ) {
378+ revocationChecker .setOptions (loadRevocationOptions ());
379+ }
380+ if (ocspResponderURL != null ) {
381+ revocationChecker .setOcspResponder (new java .net .URI (ocspResponderURL ));
382+ }
383+ pkixParams .addCertPathChecker (revocationChecker );
384+
385+
386+ // Add a certPathChecker to log soft fail exceptions caught by the revocation checker.
387+ pkixParams .addCertPathChecker (new PKIXCertPathChecker () {
388+ @ Override
389+ public void init (boolean forward ) throws CertPathValidatorException {
390+ }
391+
392+ @ Override
393+ public boolean isForwardCheckingSupported () {
394+ return revocationChecker .isForwardCheckingSupported ();
395+ }
396+
397+ @ Override
398+ public Set <String > getSupportedExtensions () {
399+ return revocationChecker .getSupportedExtensions ();
400+ }
401+
402+ @ Override
403+ public void check (Certificate cert , Collection <String > unresolvedCritExts ) throws CertPathValidatorException {
404+ List <CertPathValidatorException > softFailExceptions = revocationChecker .getSoftFailExceptions ();
405+
406+ if (softFailExceptions != null ) {
407+ for (CertPathValidatorException e : softFailExceptions ) {
408+ // Filter soft failure exceptions related to cert.
409+ // The check method may be invoked for all certificates in the path and the list of
410+ // the soft failure exceptions is cleared only before the first certificate in the path.
411+ if (e .getIndex () >= 0 && e .getCertPath ().getCertificates ().get (e .getIndex ()).equals (cert )) {
412+ String certSubject = null ;
413+ if (cert instanceof X509Certificate ) {
414+ certSubject = ((X509Certificate ) cert ).getSubjectX500Principal ().getName ();
415+ }
416+
417+ ActiveMQClientLogger .LOGGER .softFailException (certSubject , e );
418+ }
419+ }
420+ }
421+ }
422+ });
423+ }
424+
425+ protected Set <PKIXRevocationChecker .Option > loadRevocationOptions () {
426+ String [] revocationOptionNames = crcOptions .split ("," );
427+
428+ Set <PKIXRevocationChecker .Option > revocationOptions = new HashSet <>();
429+ for (String revocationOptionName : revocationOptionNames ) {
430+ revocationOptions .add (PKIXRevocationChecker .Option .valueOf (revocationOptionName ));
431+ }
432+
433+ return revocationOptions ;
434+ }
435+
313436 private TrustManager [] loadTrustManagers () throws Exception {
314437 TrustManagerFactory trustManagerFactory = loadTrustManagerFactory ();
315438 if (trustManagerFactory == null ) {
0 commit comments