/*****************************************************************************
* Copyright (c) 2008 g-Eclipse Consortium
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Initial development of the original code was made for the
* g-Eclipse project founded by European Union
* project number: FP6-IST-034327 http://www.geclipse.eu/
*
* Contributors:
* Mathias Stuempert - initial API and implementation
*****************************************************************************/
package eu.geclipse.core.internal.security;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertPath;
import java.security.cert.CertPathValidator;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import javax.net.ssl.X509TrustManager;
/**
* Internal implementation of the {@link X509TrustManager}.
*/
public class CertificateTrustManager
implements X509TrustManager {
/**
* The slave manager.
*/
private X509TrustManager slaveTrustManager;
/**
* Create a new manager without any slave.
*/
public CertificateTrustManager() {
this( null );
}
/**
* Create a new manager with the specified slave.
* @param slave
*/
public CertificateTrustManager( final X509TrustManager slave ) {
this.slaveTrustManager = slave;
}
/* (non-Javadoc)
* @see javax.net.ssl.X509TrustManager#checkClientTrusted(java.security.cert.X509Certificate[], java.lang.String)
*/
public void checkClientTrusted( final X509Certificate[] chain,
final String authType )
throws CertificateException {
if ( this.slaveTrustManager != null ) {
try {
this.slaveTrustManager.checkClientTrusted( chain, authType );
} catch ( CertificateException certExc ) {
checkTrust( chain, authType );
}
} else {
checkTrust( chain, authType );
}
}
/* (non-Javadoc)
* @see javax.net.ssl.X509TrustManager#checkServerTrusted(java.security.cert.X509Certificate[], java.lang.String)
*/
public void checkServerTrusted( final X509Certificate[] chain,
final String authType )
throws CertificateException {
if ( this.slaveTrustManager != null ) {
try {
this.slaveTrustManager.checkServerTrusted( chain, authType );
} catch ( CertificateException certExc ) {
checkTrust( chain, authType );
}
} else {
checkTrust( chain, authType );
}
}
/* (non-Javadoc)
* @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
*/
public X509Certificate[] getAcceptedIssuers() {
return this.slaveTrustManager != null ? this.slaveTrustManager.getAcceptedIssuers() : new X509Certificate[ 0 ];
}
/**
* Check the trust for the specified certificate chain.
*
* @param chain The chain to be checked.
* @param authType The auth type.
* @throws CertificateException If an error occurs.
*/
private void checkTrust( final X509Certificate[] chain,
final String authType )
throws CertificateException {
Set< TrustAnchor > trustAnchors = CertificateManager.getManager().getTrustAnchors();
boolean needsFurtherVerification = true;
if ( ( trustAnchors != null ) && ( trustAnchors.size() > 0 ) ) {
needsFurtherVerification = false;
try {
CertificateFactory certFactory = CertificateFactory.getInstance( "X.509" ); //$NON-NLS-1$
List< X509Certificate > certList = Arrays.asList( chain );
CertPath certPath = certFactory.generateCertPath( certList );
CertPathValidator validator = CertPathValidator.getInstance( "PKIX" ); //$NON-NLS-1$
PKIXParameters params = new PKIXParameters( trustAnchors );
// TODO mathias incorporate CRLs
params.setRevocationEnabled( false );
validator.validate( certPath, params );
} catch ( NoSuchAlgorithmException nsaExc ) {
throw new CertificateException( nsaExc );
} catch( InvalidAlgorithmParameterException iapExc ) {
throw new CertificateException( iapExc );
} catch( CertPathValidatorException cpvExc ) {
// The cert chain did not validate, so try with trust verifiers
needsFurtherVerification = true;
}
}
if ( needsFurtherVerification
&& ! CertificateTrustVerifier.getVerifier().verifyTrust( chain ).isTrusted() ) {
throw new CertificateException( Messages.getString("CertificateTrustManager.cert_chain_not_valid") ); //$NON-NLS-1$
}
}
}