/************************************************************************* * Copyright 2009-2014 Eucalyptus Systems, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * * Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta * CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need * additional information or have any questions. ************************************************************************/ package com.eucalyptus.crypto.util; import java.net.Socket; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.List; import java.util.Set; import javax.net.ssl.SSLEngine; import javax.net.ssl.X509ExtendedTrustManager; import com.eucalyptus.util.CollectionUtils; import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableList; import com.google.common.collect.Sets; /** * */ public class DelegatingX509ExtendedTrustManager extends X509ExtendedTrustManager { private final List<X509ExtendedTrustManager> delegates; private final Supplier<Boolean> enabled; public DelegatingX509ExtendedTrustManager( final Iterable<X509ExtendedTrustManager> delegates ) { this( delegates, Suppliers.ofInstance( true ) ); } public DelegatingX509ExtendedTrustManager( final Iterable<X509ExtendedTrustManager> delegates, final Supplier<Boolean> enabled ) { this.delegates = ImmutableList.copyOf( delegates ); this.enabled = enabled; } @Override public void checkClientTrusted( final X509Certificate[] chain, final String authType ) throws CertificateException { checkTrusted( new DelegatedTrustChecker( ) { @Override public void checkTrusted( final X509ExtendedTrustManager trustManager ) throws CertificateException { trustManager.checkClientTrusted( chain, authType ); } } ); } @Override public void checkServerTrusted( final X509Certificate[] chain, final String authType ) throws CertificateException { checkTrusted( new DelegatedTrustChecker( ) { @Override public void checkTrusted( final X509ExtendedTrustManager trustManager ) throws CertificateException { trustManager.checkServerTrusted( chain, authType ); } } ); } @Override public void checkClientTrusted( final X509Certificate[] chain, final String authType, final Socket socket ) throws CertificateException { checkTrusted( new DelegatedTrustChecker( ) { @Override public void checkTrusted( final X509ExtendedTrustManager trustManager ) throws CertificateException { trustManager.checkClientTrusted( chain, authType, socket ); } } ); } @Override public void checkServerTrusted( final X509Certificate[] chain, final String authType, final Socket socket ) throws CertificateException { checkTrusted( new DelegatedTrustChecker( ) { @Override public void checkTrusted( final X509ExtendedTrustManager trustManager ) throws CertificateException { trustManager.checkServerTrusted( chain, authType, socket ); } } ); } @Override public void checkClientTrusted( final X509Certificate[] chain, final String authType, final SSLEngine sslEngine ) throws CertificateException { checkTrusted( new DelegatedTrustChecker( ) { @Override public void checkTrusted( final X509ExtendedTrustManager trustManager ) throws CertificateException { trustManager.checkClientTrusted( chain, authType, sslEngine ); } } ); } @Override public void checkServerTrusted( final X509Certificate[] chain, final String authType, final SSLEngine sslEngine ) throws CertificateException { checkTrusted( new DelegatedTrustChecker( ) { @Override public void checkTrusted( final X509ExtendedTrustManager trustManager ) throws CertificateException { trustManager.checkServerTrusted( chain, authType, sslEngine ); } } ); } @Override public X509Certificate[] getAcceptedIssuers( ) { final Set<X509Certificate> issuers = Sets.newLinkedHashSet( ); if ( enabled.get( ) ) for ( final X509ExtendedTrustManager delegate : delegates ) { issuers.addAll( Arrays.asList( delegate.getAcceptedIssuers( ) ) ); } return issuers.toArray( new X509Certificate[ issuers.size( ) ] ); } private static interface DelegatedTrustChecker { void checkTrusted( X509ExtendedTrustManager trustManager ) throws CertificateException; } private void checkTrusted( final DelegatedTrustChecker checker ) throws CertificateException { if ( !enabled.get( ) ) { throw new CertificateException( "Delegates disabled" ); } final Optional<CertificateException> resultException = CollectionUtils.reduce( delegates, Optional.of( new CertificateException( "No delegates" ) ), new Function<Optional<CertificateException>,Function<X509ExtendedTrustManager,Optional<CertificateException>>>( ){ @Override public Function<X509ExtendedTrustManager, Optional<CertificateException>> apply( final Optional<CertificateException> previousException ) { return new Function<X509ExtendedTrustManager, Optional<CertificateException>>(){ @Override public Optional<CertificateException> apply( final X509ExtendedTrustManager trustManager ) { Optional<CertificateException> resultException = Optional.absent( ); if ( previousException.isPresent( ) ) { try { checker.checkTrusted( trustManager ); } catch ( final CertificateException e ) { resultException = Optional.of( e ); } } return resultException; } }; } } ); if ( resultException.isPresent( ) ) { throw resultException.get( ); } } }