/******************************************************************************* * Copyright (c)2008 IBM Corporation and others. * 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 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.ecf.internal.ssl; import java.io.IOException; import java.security.cert.*; import javax.net.ssl.*; import org.eclipse.osgi.service.security.TrustEngine; import org.osgi.framework.*; import org.osgi.util.tracker.ServiceTracker; public class ECFTrustManager implements X509TrustManager, BundleActivator { private static volatile BundleContext context; private volatile ServiceTracker trustEngineTracker = null; private ServiceRegistration socketFactoryRegistration; private ServiceRegistration serverSocketFactoryRegistration; public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException { // verify the cert chain verify(certs, authType); final TrustEngine[] engines = getTrustEngines(); Certificate foundCert = null; for (int i = 0; i < engines.length; i++) { try { foundCert = engines[i].findTrustAnchor(certs); if (null != foundCert) return; // cert chain is trust } catch (final IOException e) { final CertificateException ce = new ECFCertificateException( "Error occurs when finding trust anchor in the cert chain", certs, authType); //$NON-NLS-1$ ce.initCause(ce); throw ce; } } if (null == foundCert) throw new ECFCertificateException( "Valid cert chain, but no trust certificate found!", certs, authType); //$NON-NLS-1$ } private void verify(X509Certificate[] certs, String authType) throws CertificateException { final int len = certs.length; for (int i = 0; i < len; i++) { final X509Certificate currentX509Cert = certs[i]; try { if (i == len - 1) { if (currentX509Cert.getSubjectDN().equals( currentX509Cert.getIssuerDN())) currentX509Cert.verify(currentX509Cert.getPublicKey()); } else { final X509Certificate nextX509Cert = certs[i + 1]; currentX509Cert.verify(nextX509Cert.getPublicKey()); } } catch (final Exception e) { final CertificateException ce = new ECFCertificateException( "Certificate chain is not valid", certs, authType); //$NON-NLS-1$ ce.initCause(e); throw ce; } } } /** * @throws CertificateException * not actually thrown by method, since checkClientTrusted is * unsupported. */ public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { // only for client authentication throw new UnsupportedOperationException("Not implemented yet"); //$NON-NLS-1$ } public X509Certificate[] getAcceptedIssuers() { // only for client authentication return null; } public void start(BundleContext context1) throws Exception { ECFTrustManager.context = context1; socketFactoryRegistration = context1.registerService( SSLSocketFactory.class.getName(), new ECFSSLSocketFactory(), null); serverSocketFactoryRegistration = context1.registerService( SSLServerSocketFactory.class.getName(), new ECFSSLServerSocketFactory(), null); } public void stop(BundleContext context1) throws Exception { if (socketFactoryRegistration != null) { socketFactoryRegistration.unregister(); socketFactoryRegistration = null; } if (serverSocketFactoryRegistration != null) { serverSocketFactoryRegistration.unregister(); serverSocketFactoryRegistration = null; } if (trustEngineTracker != null) { trustEngineTracker.close(); trustEngineTracker = null; } ECFTrustManager.context = null; } private TrustEngine[] getTrustEngines() { if (trustEngineTracker == null) { trustEngineTracker = new ServiceTracker(context, TrustEngine.class.getName(), null); trustEngineTracker.open(); } final Object objs[] = trustEngineTracker.getServices(); final TrustEngine[] result = new TrustEngine[objs.length]; System.arraycopy(objs, 0, result, 0, objs.length); return result; } }