alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*******************************************************************************
 * Copyright (c) 2006, 2007 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.osgi.internal.verifier;

import java.io.File;
import java.io.IOException;
import java.net.URLConnection;
import java.security.Security;
import java.util.Hashtable;
import java.util.Properties;
import org.eclipse.osgi.baseadaptor.*;
import org.eclipse.osgi.baseadaptor.bundlefile.*;
import org.eclipse.osgi.baseadaptor.hooks.AdaptorHook;
import org.eclipse.osgi.baseadaptor.hooks.BundleFileWrapperFactoryHook;
import org.eclipse.osgi.framework.adaptor.BundleData;
import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
import org.eclipse.osgi.framework.internal.core.AbstractBundle;
import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
import org.eclipse.osgi.framework.log.FrameworkLog;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.internal.provisional.verifier.*;
import org.eclipse.osgi.util.ManifestElement;
import org.osgi.framework.*;
import org.osgi.util.tracker.ServiceTracker;

/**
 * Implements signed bundle hook support for the framework
 */
public class SignedBundleHook implements AdaptorHook, BundleFileWrapperFactoryHook, HookConfigurator, CertificateVerifierFactory {
	static final int VERIFY_CERTIFICATE = 0x01;
	static final int VERIFY_TRUST = 0x02;
	static final int VERIFY_RUNTIME = 0x04;
	static final int VERIFY_ALL = VERIFY_CERTIFICATE | VERIFY_TRUST | VERIFY_RUNTIME;
	private static String SUPPORT_CERTIFICATE = "certificate"; //$NON-NLS-1$
	private static String SUPPORT_TRUST = "trust"; //$NON-NLS-1$
	private static String SUPPORT_RUNTIME = "runtime"; //$NON-NLS-1$
	private static String SUPPORT_ALL = "all"; //$NON-NLS-1$
	private static String SUPPORT_TRUE = "true"; //$NON-NLS-1$

	private static ServiceTracker trustAuthorityTracker;
	private static ServiceTracker certFactoryVerifierTracker;

	private static BaseAdaptor ADAPTOR;
	private static String SIGNED_BUNDLE_SUPPORT = "osgi.support.signature.verify"; //$NON-NLS-1$
	private static int supportSignedBundles;
	private static final String systemTrustFile = System.getProperty("java.home") + "/lib/security/cacerts"; //TODO: comes from configuration!
	private static CertificateTrustAuthority systemTrustAuthority = new KeyStoreTrustAuthority(systemTrustFile, "JKS", "changeit".toCharArray()); //TODO: comes from configuration!
	private static IBundleLoadTimeHandler noOpLoadTimeHandler = new NoOpLoadTimeHandler();
	private static IBundleLoadTimeHandler defaultLoadTimeHandler;

	private ServiceRegistration certVerifierReg;
	private ServiceRegistration trustAuthorityReg;
	private ServiceRegistration loadTimeAuthorityReg;

	public boolean matchDNChain(String pattern, String dnChain[]) {
		boolean satisfied = false;
		if (dnChain != null) {
			for (int i = 0; i < dnChain.length; i++)
				if (DNChainMatching.match(dnChain[i], pattern)) {
					satisfied = true;
					break;
				}
		}
		return satisfied;
	}

	public void initialize(BaseAdaptor adaptor) {
		SignedBundleHook.ADAPTOR = adaptor;
	}

	public void frameworkStart(BundleContext context) throws BundleException {
		//		context.addBundleListener(new BundleInstallListener(ADAPTOR.getState()));

		certVerifierReg = context.registerService(CertificateVerifierFactory.class.getName(), this, null);

		/* Register the system 'lib/security/cacerts' file as a trust authority */
		Hashtable properties = new Hashtable(7);
		properties.put(Constants.SERVICE_RANKING, new Integer(Integer.MIN_VALUE));
		properties.put(JarVerifierConstant.TRUST_AUTHORITY, JarVerifierConstant.DEFAULT_TRUST_AUTHORITY);
		trustAuthorityReg = context.registerService(CertificateTrustAuthority.class.getName(), systemTrustAuthority, properties);

		Hashtable loadtimePro = new Hashtable(7);
		loadtimePro.put(Constants.SERVICE_RANKING, new Integer(Integer.MIN_VALUE));
		loadtimePro.put(JarVerifierConstant.LOADTIME_AUTHORITY, JarVerifierConstant.DEFAULT_LOADTIME_AUTHORITY);

		String supportLoadTimeCert = FrameworkProperties.getProperty("osgi.certificate.bundle.loadtime.authority"); //$NON-NLS-1$
		if (null != supportLoadTimeCert) {
			//			FrameworkProperties.setProperty("osgi.support.signature.verify", "certificate,trust,runtime");

			// need to install the load time policy defined by the osgi.certificate.bundle.loadtime.authority property
			System.err.println("Install the load time policy: " + supportLoadTimeCert);

			// @Todo log that default load time handler has been installed
			defaultLoadTimeHandler = new DefaultLoadTimeHandler(context);
			loadTimeAuthorityReg = context.registerService(IBundleLoadTimeHandler.class.getName(), defaultLoadTimeHandler, properties);
		} else {
			loadTimeAuthorityReg = context.registerService(IBundleLoadTimeHandler.class.getName(), noOpLoadTimeHandler, properties);
		}
	}

	public void frameworkStop(BundleContext context) throws BundleException {
		if (certVerifierReg != null) {
			certVerifierReg.unregister();
			certVerifierReg = null;
		}
		if (trustAuthorityReg != null) {
			trustAuthorityReg.unregister();
			trustAuthorityReg = null;
		}
		if (trustAuthorityTracker != null) {
			trustAuthorityTracker.close();
			trustAuthorityTracker = null;
		}
		if (loadTimeAuthorityReg != null) {
			loadTimeAuthorityReg.unregister();
			loadTimeAuthorityReg = null;
		}
	}

	public void frameworkStopping(BundleContext context) {
		// do nothing
	}

	public void addProperties(Properties properties) {
		// do nothing
	}

	public URLConnection mapLocationToURLConnection(String location) throws IOException {
		return null;
	}

	public void handleRuntimeError(Throwable error) {
		// do nothing
	}

	public FrameworkLog createFrameworkLog() {
		return null;
	}

	public BundleFile wrapBundleFile(BundleFile bundleFile, Object content, BaseData data, boolean base) {

		//		AbstractBundle ab = data.getBundle();
		//		ab.getbun

		//		BundleDescription disableBundleDescriptions1 = ADAPTOR.getState().getBundle(1);

		// pass the bundle descripton to some policy

		try {
			if (bundleFile != null) {
				SignedStorageHook hook = (SignedStorageHook) data.getStorageHook(SignedStorageHook.KEY);
				SignedBundleFile signedBaseFile;
				if (base && hook != null) {
					if (hook.signedBundleFile == null)
						hook.signedBundleFile = new SignedBundleFile();
					signedBaseFile = hook.signedBundleFile;
				} else
					signedBaseFile = new SignedBundleFile();
				signedBaseFile.setBundleFile(bundleFile, supportSignedBundles);
				if (signedBaseFile.isSigned()) // only use the signed file if there are certs
					bundleFile = signedBaseFile;
				else if (base) // if the base is not signed null out the hook.signedBundleFile
					hook.signedBundleFile = null;
			}
		} catch (IOException e) {
			// do nothing; its not your responsibility the error will be addressed later
		}
		return bundleFile;
	}

	public void addHooks(HookRegistry hookRegistry) {
		hookRegistry.addAdaptorHook(this);

		//  -Dosgi.support.signature.verify=certificate,trust
		String supportLoadTimeCert = FrameworkProperties.getProperty("osgi.certificate.bundle.loadtime.authority"); //$NON-NLS-1$
		if (null != supportLoadTimeCert) {
			FrameworkProperties.setProperty("osgi.support.signature.verify", "certificate,trust,runtime");
		}

		String[] support = ManifestElement.getArrayFromList(FrameworkProperties.getProperty(SIGNED_BUNDLE_SUPPORT), ","); //$NON-NLS-1$
		for (int i = 0; i < support.length; i++) {
			if (SUPPORT_CERTIFICATE.equals(support[i]))
				supportSignedBundles |= VERIFY_CERTIFICATE;
			else if (SUPPORT_TRUST.equals(support[i]))
				supportSignedBundles |= VERIFY_CERTIFICATE | VERIFY_TRUST;
			else if (SUPPORT_RUNTIME.equals(support[i]))
				supportSignedBundles |= VERIFY_CERTIFICATE | VERIFY_RUNTIME;
			else if (SUPPORT_TRUE.equals(support[i]) || SUPPORT_ALL.equals(support[i]))
				supportSignedBundles |= VERIFY_ALL;
		}
		if ((supportSignedBundles & VERIFY_CERTIFICATE) != 0) {
			hookRegistry.addStorageHook(new SignedStorageHook());
			hookRegistry.addBundleFileWrapperFactoryHook(this);
		}
	}

	public CertificateVerifier getVerifier(File content) throws IOException {
		if (content == null)
			throw new IllegalArgumentException("null content"); //$NON-NLS-1$
		BundleFile contentBundleFile;
		if (content.isDirectory())
			contentBundleFile = new DirBundleFile(content);
		else
			contentBundleFile = new ZipBundleFile(content, null);
		SignedBundleFile result = new SignedBundleFile();
		result.setBundleFile(contentBundleFile, VERIFY_ALL);
		return result;
	}

	public CertificateVerifier getVerifier(Bundle bundle) throws IOException {
		BundleData data = ((AbstractBundle) bundle).getBundleData();
		if (!(data instanceof BaseData))
			throw new IllegalArgumentException("Invalid bundle object.  No BaseData found."); //$NON-NLS-1$
		SignedStorageHook hook = (SignedStorageHook) ((BaseData) data).getStorageHook(SignedStorageHook.KEY);
		SignedBundleFile signedBundle = hook != null ? hook.signedBundleFile : null;
		if (signedBundle != null)
			return signedBundle; // just reuse the verifier from the bundle file
		return getVerifier(((BaseData) data).getBundleFile().getBaseFile()); // must create a new verifier using the raw file
	}

	static void log(String msg, int severity, Throwable t) {
		if (SignedBundleHook.ADAPTOR == null) {
			System.err.println(msg);
			t.printStackTrace();
			return;
		}
		FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, severity, 0, msg, 0, t, null);
		SignedBundleHook.ADAPTOR.getFrameworkLog().log(entry);
	}

	static BundleContext getContext() {
		if (ADAPTOR == null)
			return null;
		return ADAPTOR.getContext();
	}

	static CertificateTrustAuthority getSystemTrustAuthority() {
		// read the certs chain security property and open the service tracker if not null
		BundleContext context = SignedBundleHook.getContext();
		if (context == null)
			return systemTrustAuthority;
		if (trustAuthorityTracker == null) {
			// read the trust provider security property
			String trustAuthorityProp = Security.getProperty(JarVerifierConstant.TRUST_AUTHORITY);
			Filter filter = null;
			if (trustAuthorityProp != null)
				try {
					filter = FrameworkUtil.createFilter("(&(" + Constants.OBJECTCLASS + "=" + CertificateTrustAuthority.class.getName() + ")(" + JarVerifierConstant.TRUST_AUTHORITY + "=" + trustAuthorityProp + "))"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$//$NON-NLS-5$
				} catch (InvalidSyntaxException e) {
					e.printStackTrace();
					// do nothing just use no filter TODO we may want to log something
				}
			if (filter != null) {
				trustAuthorityTracker = new ServiceTracker(context, filter, null);
			} else
				trustAuthorityTracker = new ServiceTracker(context, CertificateTrustAuthority.class.getName(), null);
			trustAuthorityTracker.open();
		}
		return (CertificateTrustAuthority) trustAuthorityTracker.getService();
	}

	static CertificateVerifierFactory getCertificateVerifierFactory() {
		BundleContext context = SignedBundleHook.getContext();

		if (null == certFactoryVerifierTracker) {
			certFactoryVerifierTracker = new ServiceTracker(context, CertificateVerifierFactory.class.getName(), null);
			certFactoryVerifierTracker.open();
		}

		return (CertificateVerifierFactory) certFactoryVerifierTracker.getService();
	}

	public CertificateVerifier getVerifier(BundleData data) throws IOException {
		if (!(data instanceof BaseData))
			throw new IllegalArgumentException("Invalid bundle object.  No BaseData found."); //$NON-NLS-1$
		BundleFile bundleFile = ((BaseData) data).getBundleFile();
		if (bundleFile instanceof SignedBundleFile)
			return (SignedBundleFile) bundleFile; // just reuse the verifier from the bundle file
		return getVerifier(bundleFile.getBaseFile()); // must create a new verifier using the raw file
	}

}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.