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