Implement 4.3 security checks (FELIX-3110).

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1169690 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
index 98a8282..092ac68 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
@@ -368,7 +368,7 @@
 
     public <S> ServiceReference<S> getServiceReference(Class<S> clazz)
     {
-        throw new UnsupportedOperationException("Not supported yet.");
+        return (ServiceReference<S>) getServiceReference(clazz.getName());
     }
 
     private ServiceReference getBestServiceReference(ServiceReference[] refs)
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 918a39c..83e8b10 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
@@ -27,8 +27,10 @@
 
 import org.apache.felix.framework.cache.BundleArchive;
 import org.apache.felix.framework.ext.SecurityProvider;
+import org.apache.felix.framework.util.SecurityManagerEx;
 import org.apache.felix.framework.util.StringMap;
 import org.apache.felix.framework.util.Util;
+import org.osgi.framework.AdaptPermission;
 import org.osgi.framework.AdminPermission;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleActivator;
@@ -46,7 +48,7 @@
 
 class BundleImpl implements Bundle, BundleRevisions
 {
-    // No one should use this field directlhttp://www.youtube.com/watch?v=zQwxwPDU4bwy, use getFramework() instead.
+    // No one should use this field directly, use getFramework() instead.
     private final Felix __m_felix;
 
     private final BundleArchive m_archive;
@@ -1009,9 +1011,26 @@
         // Uninstall the bundle.
         getFramework().uninstallBundle(this);
     }
-
+    private static final SecurityManagerEx m_smEx = new SecurityManagerEx();
+    private static final ClassLoader m_classloader = Felix.class.getClassLoader();
+    
+    <A> void checkAdapt(Class<A> type) 
+    {
+        Object sm = System.getSecurityManager();
+        if ((sm != null) && (getFramework().getSecurityProvider() != null))
+        {
+            Class caller = m_smEx.getClassContext()[3];
+            if (((Felix.m_secureAction.getClassLoader(caller) != m_classloader) ||
+                !caller.getName().startsWith("org.apache.felix.framework."))) 
+            {
+                ((SecurityManager) sm).checkPermission(
+                    new AdaptPermission(type.getName(), this, AdaptPermission.ADAPT));
+            }
+        }
+    }
     public synchronized <A> A adapt(Class<A> type)
     {
+        checkAdapt(type);
         if (type == BundleStartLevel.class)
         {
             return (A) getFramework().adapt(FrameworkStartLevelImpl.class)
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
index 2dcf8f8..f63755c 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
@@ -40,8 +40,9 @@
 import java.util.SortedMap;
 import java.util.TreeMap;
 import java.util.TreeSet;
-import org.apache.felix.framework.cache.JarContent;
+
 import org.apache.felix.framework.cache.Content;
+import org.apache.felix.framework.cache.JarContent;
 import org.apache.felix.framework.capabilityset.SimpleFilter;
 import org.apache.felix.framework.resolver.ResolveException;
 import org.apache.felix.framework.resolver.ResourceNotFoundException;
@@ -55,8 +56,10 @@
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.BundleReference;
+import org.osgi.framework.CapabilityPermission;
 import org.osgi.framework.Constants;
 import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.PackagePermission;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.hooks.weaving.WeavingException;
 import org.osgi.framework.hooks.weaving.WeavingHook;
@@ -343,6 +346,30 @@
                 }
             }
         }
+        if (System.getSecurityManager() != null)
+        {
+            for (Iterator<BundleCapability> iter = capList.iterator();iter.hasNext();)
+            {
+                BundleCapability cap = iter.next();
+                if (cap.getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE))
+                {
+                    if (!((BundleProtectionDomain) ((BundleRevisionImpl) cap.getRevision()).getProtectionDomain()).impliesDirect(
+                        new PackagePermission((String) cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE), PackagePermission.EXPORTONLY)))
+                    {
+                        iter.remove();
+                    }
+                }
+                else if (!cap.getNamespace().equals(BundleRevision.HOST_NAMESPACE) && !cap.getNamespace().equals(BundleRevision.BUNDLE_NAMESPACE) && 
+                    !cap.getNamespace().equals("osgi.ee")) 
+                {
+                    if (!((BundleProtectionDomain) ((BundleRevisionImpl) cap.getRevision()).getProtectionDomain()).impliesDirect(
+                        new CapabilityPermission(cap.getNamespace(), CapabilityPermission.PROVIDE)))
+                    {
+                        iter.remove();
+                    }
+                }
+            }
+        }
         m_resolvedCaps = Collections.unmodifiableList(capList);
         m_includedPkgFilters = (includedPkgFilters.isEmpty())
             ? Collections.EMPTY_MAP : includedPkgFilters;
@@ -1954,7 +1981,7 @@
                                 // we used to define the class.
                                 if (wci != null)
                                 {
-                                    bytes = wovenBytes = wci.getBytes();
+                                    bytes = wovenBytes = wci._getBytes();
                                     wovenImports = wci.getDynamicImportsInternal();
 
                                     // Try to add any woven dynamic imports, since they
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 f9200e5..a8e6958 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -469,6 +469,7 @@
     @Override
     public <A> A adapt(Class<A> type)
     {
+        checkAdapt(type);
         if ((type == FrameworkWiring.class)
             || (type == FrameworkWiringImpl.class))
         {
diff --git a/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java b/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java
index f5ec26a..053ba9f 100644
--- a/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java
+++ b/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java
@@ -47,6 +47,7 @@
 import org.osgi.framework.BundleEvent;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.BundlePermission;
+import org.osgi.framework.CapabilityPermission;
 import org.osgi.framework.Constants;
 import org.osgi.framework.PackagePermission;
 import org.osgi.framework.ServiceReference;
@@ -1272,47 +1273,10 @@
                 Set<BundleCapability> matches = capSet.match(sf, obeyMandatory);
                 for (BundleCapability cap : matches)
                 {
-                    if (System.getSecurityManager() != null)
+                    if (filteredBySecurity(req, cap)) 
                     {
-                        if (req.getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE) && (
-                            !((BundleProtectionDomain) ((BundleRevisionImpl) cap.getRevision()).getProtectionDomain()).impliesDirect(
-                                new PackagePermission((String) cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE),
-                                PackagePermission.EXPORTONLY)) ||
-                                !((reqRevision == null) ||
-                                    ((BundleProtectionDomain) reqRevision.getProtectionDomain()).impliesDirect(
-                                        new PackagePermission((String) cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE),
-                                        cap.getRevision().getBundle(),PackagePermission.IMPORT))
-                                )))
-                        {
-                            if (reqRevision != cap.getRevision())
-                            {
-                                continue;
-                            }
-                        }
-                        else if (req.getNamespace().equals(BundleRevision.BUNDLE_NAMESPACE) && (
-                            !((BundleProtectionDomain) ((BundleRevisionImpl) cap.getRevision()).getProtectionDomain()).impliesDirect(
-                                new BundlePermission(cap.getRevision().getSymbolicName(), BundlePermission.PROVIDE)) ||
-                                !((reqRevision == null) ||
-                                    ((BundleProtectionDomain) reqRevision.getProtectionDomain()).impliesDirect(
-                                        new BundlePermission(reqRevision.getSymbolicName(), BundlePermission.REQUIRE))
-                                )))
-                        {
-                            continue;
-                        }
-                        else if (req.getNamespace().equals(BundleRevision.HOST_NAMESPACE) &&
-                            (!((BundleProtectionDomain) reqRevision.getProtectionDomain())
-                                .impliesDirect(new BundlePermission(
-                                    reqRevision.getSymbolicName(),
-                                    BundlePermission.FRAGMENT))
-                            || !((BundleProtectionDomain) ((BundleRevisionImpl) cap.getRevision()).getProtectionDomain())
-                                .impliesDirect(new BundlePermission(
-                                    cap.getRevision().getSymbolicName(),
-                                    BundlePermission.HOST))))
-                        {
-                            continue;
-                        }
+                        continue;
                     }
-
                     if (req.getNamespace().equals(BundleRevision.HOST_NAMESPACE)
                         && (cap.getRevision().getWiring() != null))
                     {
@@ -1360,6 +1324,68 @@
             return result;
         }
 
+        private boolean filteredBySecurity(BundleRequirement req, BundleCapability cap) {
+            if (System.getSecurityManager() != null)
+            {
+                BundleRevisionImpl reqRevision = (BundleRevisionImpl) req.getRevision();
+               
+                if (req.getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE))
+                {
+                    if (!((BundleProtectionDomain) ((BundleRevisionImpl) cap.getRevision()).getProtectionDomain()).impliesDirect(
+                        new PackagePermission((String) cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE),
+                        PackagePermission.EXPORTONLY)) ||
+                        !((reqRevision == null) ||
+                            ((BundleProtectionDomain) reqRevision.getProtectionDomain()).impliesDirect(
+                                new PackagePermission((String) cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE),
+                                cap.getRevision().getBundle(),PackagePermission.IMPORT))
+                        ))
+                    {
+                        if (reqRevision != cap.getRevision())
+                        {
+                            return true;
+                        }
+                    }
+                }
+                else if (req.getNamespace().equals(BundleRevision.BUNDLE_NAMESPACE))
+                {   if (!((BundleProtectionDomain) ((BundleRevisionImpl) cap.getRevision()).getProtectionDomain()).impliesDirect(
+                        new BundlePermission(cap.getRevision().getSymbolicName(), BundlePermission.PROVIDE)) ||
+                        !((reqRevision == null) ||
+                            ((BundleProtectionDomain) reqRevision.getProtectionDomain()).impliesDirect(
+                                new BundlePermission(reqRevision.getSymbolicName(), BundlePermission.REQUIRE))
+                        ))
+                    {
+                        return true;
+                    }
+                }
+                else if (req.getNamespace().equals(BundleRevision.HOST_NAMESPACE)) 
+                { 
+                    if (!((BundleProtectionDomain) reqRevision.getProtectionDomain())
+                        .impliesDirect(new BundlePermission(
+                            reqRevision.getSymbolicName(),
+                            BundlePermission.FRAGMENT))
+                    || !((BundleProtectionDomain) ((BundleRevisionImpl) cap.getRevision()).getProtectionDomain())
+                        .impliesDirect(new BundlePermission(
+                            cap.getRevision().getSymbolicName(),
+                            BundlePermission.HOST)))
+                    {
+                        return true;
+                    }
+                } 
+                else  if (!req.getNamespace().equals("osgi.ee"))
+                {
+                    if (!((BundleProtectionDomain) ((BundleRevisionImpl) cap.getRevision()).getProtectionDomain()).impliesDirect(
+                        new CapabilityPermission(req.getNamespace(), CapabilityPermission.PROVIDE))
+                        || 
+                        !((reqRevision == null) || ((BundleProtectionDomain) reqRevision.getProtectionDomain()).impliesDirect(
+                        new CapabilityPermission(req.getNamespace(), cap.getAttributes(), cap.getRevision().getBundle(), CapabilityPermission.REQUIRE)))) 
+                    {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+
         public void checkExecutionEnvironment(BundleRevision revision) throws ResolveException
         {
             String bundleExecEnvStr = (String)
@@ -1467,4 +1493,5 @@
         revisions.add(br);
         singletons.put(br.getSymbolicName(), revisions);
     }
+
 }
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/WovenClassImpl.java b/framework/src/main/java/org/apache/felix/framework/WovenClassImpl.java
index 62522a0..8402d80 100644
--- a/framework/src/main/java/org/apache/felix/framework/WovenClassImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/WovenClassImpl.java
@@ -27,6 +27,7 @@
 import java.util.ListIterator;
 import org.apache.felix.framework.util.manifestparser.ManifestParser;
 import org.apache.felix.framework.util.manifestparser.ParsedHeaderClause;
+import org.osgi.framework.AdminPermission;
 import org.osgi.framework.Constants;
 import org.osgi.framework.hooks.weaving.WovenClass;
 import org.osgi.framework.wiring.BundleRequirement;
@@ -60,6 +61,11 @@
 
     public synchronized byte[] getBytes()
     {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+        {
+            sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+        }
         byte[] bytes = m_bytes;
         if (m_isComplete)
         {
@@ -71,6 +77,11 @@
 
     public synchronized void setBytes(byte[] bytes)
     {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+        {
+            sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+        }
         if (m_isComplete)
         {
             throw new IllegalStateException(
@@ -156,6 +167,11 @@
 
     public synchronized boolean add(String s)
     {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+        {
+            sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+        }
         if (s != null)
         {
             try
@@ -177,6 +193,11 @@
 
     public synchronized boolean remove(Object o)
     {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+        {
+            sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+        }
         return m_imports.remove(o);
     }
 
@@ -187,6 +208,11 @@
 
     public synchronized boolean addAll(Collection<? extends String> collection)
     {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+        {
+            sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+        }
         for (String s : collection)
         {
             try
@@ -207,6 +233,11 @@
 
     public synchronized boolean addAll(int i, Collection<? extends String> collection)
     {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+        {
+            sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+        }
         for (String s : collection)
         {
             try
@@ -227,11 +258,21 @@
 
     public synchronized boolean removeAll(Collection<?> collection)
     {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+        {
+            sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+        }
         return m_imports.removeAll(collection);
     }
 
     public synchronized boolean retainAll(Collection<?> collection)
     {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+        {
+            sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+        }
         return m_imports.retainAll(collection);
     }
 
@@ -247,6 +288,11 @@
 
     public synchronized String set(int i, String s)
     {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+        {
+            sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+        }
         try
         {
             List<BundleRequirement> reqs =
@@ -264,6 +310,11 @@
 
     public synchronized void add(int i, String s)
     {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+        {
+            sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+        }
         try
         {
             List<BundleRequirement> reqs =
@@ -281,6 +332,11 @@
 
     public synchronized String remove(int i)
     {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+        {
+            sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+        }
         return m_imports.remove(i);
     }
 
@@ -308,4 +364,15 @@
     {
         return m_imports.subList(i, i1);
     }
+
+    byte[] _getBytes() 
+    {
+        byte[] bytes = m_bytes;
+        if (m_isComplete)
+        {
+            bytes = new byte[m_bytes.length];
+            System.arraycopy(m_bytes, 0, bytes, 0, m_bytes.length);
+        }
+        return bytes;
+    }
 }
\ No newline at end of file