Fix a bug where we where not checking bundle signer signatures when restarting and set the signers on the codesource of a bundle (FELIX-3610,FELIX-3611)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1366063 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
index cc91544..5d72142 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
@@ -1161,23 +1161,14 @@
{
m_revisions.add(0, revision);
- // Set protection domain after adding the revision to the bundle,
- // since this requires that the bundle has a revision.
- ((BundleRevisionImpl) revision).setProtectionDomain(
- new BundleProtectionDomain(getFramework(), this));
-
- SecurityProvider sp = getFramework().getSecurityProvider();
- if ((sp != null) && (System.getSecurityManager() != null))
+ try
{
- try
- {
- sp.checkBundle(this);
- }
- catch (Exception ex)
- {
- m_revisions.remove(0);
- throw ex;
- }
+ getFramework().setBundleProtectionDomain(this, (BundleRevisionImpl) revision);
+ }
+ catch (Exception ex)
+ {
+ m_revisions.remove(0);
+ throw ex;
}
// TODO: REFACTOR - consider nulling capabilities for extension bundles
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java b/framework/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java
index 3b1e53b..2095960 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java
@@ -36,7 +36,7 @@
private final WeakReference m_revision;
// TODO: SECURITY - This should probably take a revision, not a bundle.
- BundleProtectionDomain(Felix felix, BundleImpl bundle)
+ BundleProtectionDomain(Felix felix, BundleImpl bundle, Object certificates)
throws MalformedURLException
{
super(
@@ -46,7 +46,7 @@
bundle._getLocation(),
new FakeURLStreamHandler()
),
- (Certificate[]) null),
+ (Certificate[]) certificates),
null);
m_felix = new WeakReference(felix);
m_bundle = new WeakReference(bundle);
diff --git a/framework/src/main/java/org/apache/felix/framework/Felix.java b/framework/src/main/java/org/apache/felix/framework/Felix.java
index b56f9f9..99f5aa5 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -699,6 +699,10 @@
archives = null;
}
+ // Create system bundle activator and bundle context so we can activate it.
+ setActivator(new SystemBundleActivator());
+ setBundleContext(new BundleContextImpl(m_logger, this, this));
+
// Now load all cached bundles.
for (int i = 0; (archives != null) && (i < archives.length); i++)
{
@@ -759,9 +763,6 @@
// so create a gate for that purpose.
m_shutdownGate = new ThreadGate();
- // Create system bundle activator and bundle context so we can activate it.
- setActivator(new SystemBundleActivator());
- setBundleContext(new BundleContextImpl(m_logger, this, this));
try
{
Felix.m_secureAction.startActivator(
@@ -778,6 +779,53 @@
// its bundle context to the logger so that it can track log services.
m_logger.setSystemBundleContext(_getBundleContext());
+ // We have to check with the security provider (if there is one).
+ // This is to avoid having bundles in the cache that have been tampered with
+ SecurityProvider sp = getFramework().getSecurityProvider();
+ if ((sp != null) && (System.getSecurityManager() != null))
+ {
+ boolean locked = acquireGlobalLock();
+ if (!locked)
+ {
+ throw new BundleException(
+ "Unable to acquire the global lock to check the bundle.");
+ }
+ try
+ {
+ for (Object bundle : m_installedBundles[IDENTIFIER_MAP_IDX].values())
+ {
+ try
+ {
+ if (bundle != this)
+ {
+ setBundleProtectionDomain((BundleImpl) bundle, (BundleRevisionImpl) ((BundleImpl) bundle).adapt(BundleRevisionImpl.class));
+ }
+ }
+ catch (Exception ex)
+ {
+ ((BundleImpl) bundle).close();
+ maps = new Map[] {
+ new HashMap<String, BundleImpl>(m_installedBundles[LOCATION_MAP_IDX]),
+ new TreeMap<Long, BundleImpl>(m_installedBundles[IDENTIFIER_MAP_IDX])
+ };
+ maps[LOCATION_MAP_IDX].remove(((BundleImpl) bundle)._getLocation());
+ maps[IDENTIFIER_MAP_IDX].remove(new Long(((BundleImpl) bundle).getBundleId()));
+ m_installedBundles = maps;
+
+ m_logger.log(
+ Logger.LOG_ERROR,
+ "Bundle in cache doesn't pass security check anymore.",
+ ex);
+ }
+ }
+ }
+ finally
+ {
+ // Always release the global lock.
+ releaseGlobalLock();
+ }
+ }
+
// Clear the cache of classes coming from the system bundle.
// This is only used for Felix.getBundle(Class clazz) to speed
// up class lookup for the system bundle.
@@ -793,6 +841,20 @@
}
}
+ void setBundleProtectionDomain(BundleImpl bundleImpl, BundleRevisionImpl revisionImpl) throws Exception
+ {
+ Object certificates = null;
+ SecurityProvider sp = getFramework().getSecurityProvider();
+ if ((sp != null) && (System.getSecurityManager() != null))
+ {
+ sp.checkBundle(bundleImpl);
+ Map signers = (Map) sp.getSignerMatcher(this, Bundle.SIGNERS_TRUSTED);
+ certificates = signers.keySet().toArray(new java.security.cert.Certificate[0]);
+ }
+ revisionImpl.setProtectionDomain(
+ new BundleProtectionDomain(this, bundleImpl, certificates));
+ }
+
/**
* This method starts the framework instance, which will transition the
* framework from start level 0 to its active start level as specified in