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