Implement all required security checks (FELIX-1973).
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@897661 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 acdcbda..2248d5c 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
@@ -324,34 +324,7 @@
if (sm != null)
{
- String[] objectClass = (String[]) ref.getProperty(Constants.OBJECTCLASS);
-
- if (objectClass == null)
- {
- return null;
- }
-
- boolean hasPermission = false;
-
- for (int i = 0;(i < objectClass.length) && !hasPermission;i++)
- {
- try
- {
- ((SecurityManager) sm).checkPermission(
- new ServicePermission(objectClass[i], ServicePermission.GET));
-
- hasPermission = true;
- }
- catch (Exception ex)
- {
-
- }
- }
-
- if (!hasPermission)
- {
- throw new SecurityException("No permission");
- }
+ ((SecurityManager) sm).checkPermission(new ServicePermission(ref, ServicePermission.GET));
}
return m_felix.getService(m_bundle, ref);
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 de0310c..587098b 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
@@ -40,7 +40,7 @@
private volatile int m_state;
private boolean m_useDeclaredActivationPolicy;
private BundleActivator m_activator = null;
- private BundleContext m_context = null;
+ private volatile BundleContext m_context = null;
private final Map m_cachedHeaders = new HashMap();
private long m_cachedHeadersTimestamp;
@@ -181,13 +181,19 @@
m_activator = activator;
}
- public synchronized BundleContext getBundleContext()
+ public BundleContext getBundleContext()
{
-// TODO: SECURITY - We need a security check here.
+ Object sm = System.getSecurityManager();
+
+ if (sm != null)
+ {
+ ((SecurityManager) sm).checkPermission(new AdminPermission(this, AdminPermission.CONTEXT));
+ }
+
return m_context;
}
- synchronized void setBundleContext(BundleContext context)
+ void setBundleContext(BundleContext context)
{
m_context = context;
}
@@ -620,29 +626,16 @@
for (int i = 0; i < refs.length; i++)
{
- String[] objectClass = (String[]) refs[i].getProperty(
- Constants.OBJECTCLASS);
-
- if (objectClass == null)
+ try
{
- continue;
+ ((SecurityManager) sm).checkPermission(new ServicePermission(
+ refs[i], ServicePermission.GET));
+
+ result.add(refs[i]);
}
-
- for (int j = 0; j < objectClass.length; j++)
+ catch (Exception ex)
{
- try
- {
- ((SecurityManager) sm).checkPermission(new ServicePermission(
- objectClass[j], ServicePermission.GET));
-
- result.add(refs[i]);
-
- break;
- }
- catch (Exception ex)
- {
- // Silently ignore.
- }
+ // Silently ignore.
}
}
@@ -676,29 +669,16 @@
for (int i = 0; i < refs.length; i++)
{
- String[] objectClass = (String[]) refs[i].getProperty(
- Constants.OBJECTCLASS);
-
- if (objectClass == null)
+ try
{
- continue;
+ ((SecurityManager) sm).checkPermission(new ServicePermission(
+ refs[i], ServicePermission.GET));
+
+ result.add(refs[i]);
}
-
- for (int j = 0; j < objectClass.length; j++)
+ catch (Exception ex)
{
- try
- {
- ((SecurityManager) sm).checkPermission(new ServicePermission(
- objectClass[j], ServicePermission.GET));
-
- result.add(refs[i]);
-
- break;
- }
- catch (Exception ex)
- {
- // Silently ignore.
- }
+ // Silently ignore.
}
}
@@ -864,12 +844,7 @@
public Map getSignerCertificates(int signersType)
{
// TODO: SECURITY - This needs to be adapted to our security mechanisms.
- return new HashMap();
- }
-
- Object getSignerMatcher()
- {
- return getFramework().getSignerMatcher(this);
+ return (Map) getFramework().getSignerMatcher(this, signersType);
}
public Class loadClass(String name) throws ClassNotFoundException
@@ -1061,8 +1036,16 @@
{
// This operation will increase the revision count for the bundle.
m_archive.revise(location, is);
- IModule module = createModule();
- addModule(module);
+ try
+ {
+ IModule module = createModule();
+ addModule(module);
+ }
+ catch (Exception ex)
+ {
+ m_archive.rollbackRevise();
+ throw ex;
+ }
}
synchronized boolean rollbackRevise() throws Exception
@@ -1076,13 +1059,7 @@
// be created, which is the normal case.
synchronized void addModule(IModule module) throws Exception
{
- SecurityProvider sp = getFramework().getSecurityProvider();
- if (sp != null)
- {
- // TODO: Security
- // sp.checkBundle(this);
- }
-
+ IModule[] backup = m_modules;
IModule[] dest = new IModule[m_modules.length + 1];
System.arraycopy(m_modules, 0, dest, 0, m_modules.length);
dest[m_modules.length] = module;
@@ -1092,6 +1069,20 @@
// since this requires that the bundle has a module.
module.setSecurityContext(new BundleProtectionDomain(getFramework(), this));
+ SecurityProvider sp = getFramework().getSecurityProvider();
+ if ((sp != null) && (System.getSecurityManager() != null))
+ {
+ try
+ {
+ sp.checkBundle(this);
+ }
+ catch (Exception ex)
+ {
+ m_modules = backup;
+ throw ex;
+ }
+ }
+
// TODO: REFACTOR - consider moving ModuleImpl into the framework package
// so we can null module capabilities for extension bundles so we don't
// need this check anymore.
@@ -1151,11 +1142,6 @@
return module;
}
- void setProtectionDomain(ProtectionDomain pd)
- {
- getCurrentModule().setSecurityContext(pd);
- }
-
synchronized ProtectionDomain getProtectionDomain()
{
ProtectionDomain pd = null;
@@ -1208,4 +1194,9 @@
m_lockThread = null;
}
}
+
+ BundleContext _getBundleContext()
+ {
+ return m_context;
+ }
}
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 4171f06..3aac628 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java
@@ -26,26 +26,41 @@
import java.security.ProtectionDomain;
import java.security.cert.Certificate;
+import org.apache.felix.moduleloader.IModule;
+
public class BundleProtectionDomain extends ProtectionDomain
{
private final WeakReference m_felix;
private final WeakReference m_bundle;
private final int m_hashCode;
private final String m_toString;
+ private final WeakReference m_module;
// TODO: SECURITY - This should probably take a module, not a bundle.
BundleProtectionDomain(Felix felix, BundleImpl bundle)
throws MalformedURLException
{
- super(new CodeSource(new URL(new URL(null, "location:",
- new FakeURLStreamHandler()), bundle._getLocation(),
- new FakeURLStreamHandler()), (Certificate[]) null), null);
+ super(
+ new CodeSource(
+ Felix.m_secureAction.createURL(
+ Felix.m_secureAction.createURL(null, "location:", new FakeURLStreamHandler()),
+ bundle._getLocation(),
+ new FakeURLStreamHandler()
+ ),
+ (Certificate[]) null),
+ null);
m_felix = new WeakReference(felix);
m_bundle = new WeakReference(bundle);
+ m_module = new WeakReference(bundle.getCurrentModule());
m_hashCode = bundle.hashCode();
m_toString = "[" + bundle + "]";
}
+ IModule getModule()
+ {
+ return (IModule) m_module.get();
+ }
+
public boolean implies(Permission permission)
{
Felix felix = (Felix) m_felix.get();
diff --git a/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java b/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
index 3242a72..5fb57a8 100644
--- a/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
+++ b/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
@@ -24,6 +24,7 @@
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
+import java.security.AccessControlException;
import java.security.AllPermission;
import java.util.ArrayList;
import java.util.Enumeration;
@@ -277,8 +278,16 @@
Object sm = System.getSecurityManager();
if (sm != null)
{
- ((SecurityManager) sm).checkPermission(
- new AdminPermission(bundle, AdminPermission.EXTENSIONLIFECYCLE));
+ try
+ {
+ ((SecurityManager) sm).checkPermission(
+ new AdminPermission(bundle, AdminPermission.EXTENSIONLIFECYCLE));
+ }
+ catch (SecurityException ex)
+ {
+ // TODO: security - we need to throw this exception because of the 4.2.0 ct
+ throw new AccessControlException(ex.getMessage());
+ }
}
if (!((BundleProtectionDomain) bundle.getProtectionDomain()).impliesDirect(new AllPermission()))
@@ -374,7 +383,7 @@
// TODO: KARL - This is kind of hacky, can we improve it?
felix.m_activatorList.add(activator);
- BundleContext context = felix.getBundleContext();
+ BundleContext context = felix._getBundleContext();
bundle.setBundleContext(context);
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 38a6886..3290209 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -32,7 +32,6 @@
import org.apache.felix.framework.util.manifestparser.*;
import org.apache.felix.moduleloader.*;
import org.osgi.framework.*;
-import org.osgi.framework.BundleReference;
import org.osgi.framework.hooks.service.*;
import org.osgi.service.packageadmin.ExportedPackage;
import org.osgi.service.startlevel.StartLevel;
@@ -120,6 +119,9 @@
// Shutdown thread.
private Thread m_shutdownThread = null;
private volatile ThreadGate m_shutdownGate = null;
+
+ // Security Manager created by the framework
+ private SecurityManager m_securityManager = null;
/**
* <p>
@@ -479,6 +481,46 @@
Bundle.INSTALLED | Bundle.RESOLVED | Bundle.STARTING | Bundle.ACTIVE);
try
{
+ String security = (String) m_configMap.get(Constants.FRAMEWORK_SECURITY);
+ if (security != null)
+ {
+ if (System.getSecurityManager() != null)
+ {
+ throw new SecurityException("SecurityManager already installed");
+ }
+ security = security.trim();
+ if (Constants.FRAMEWORK_SECURITY_OSGI.equalsIgnoreCase(security) || (security.length() == 0))
+ {
+ // TODO: security - we only need our own security manager to convert the exceptions
+ // because the 4.2.0 ct does expect them like this in one case.
+ System.setSecurityManager(m_securityManager = new SecurityManager()
+ {
+ public void checkPermission(Permission perm)
+ {
+ try
+ {
+ super.checkPermission(perm);
+ }
+ catch (AccessControlException ex)
+ {
+ throw new SecurityException(ex);
+ }
+ }
+ });
+ }
+ else
+ {
+ try
+ {
+ System.setSecurityManager(m_securityManager =
+ (SecurityManager) Class.forName(security).newInstance());
+ }
+ catch (Throwable t)
+ {
+ throw new SecurityException("Unable to install custom SecurityManager: " + security, t);
+ }
+ }
+ }
if ((getState() == Bundle.INSTALLED) || (getState() == Bundle.RESOLVED))
{
// Get any system bundle activators.
@@ -640,7 +682,7 @@
try
{
Felix.m_secureAction.startActivator(
- getActivator(), getBundleContext());
+ getActivator(), _getBundleContext());
}
catch (Throwable ex)
{
@@ -651,7 +693,7 @@
// Now that the system bundle is successfully created we can give
// its bundle context to the logger so that it can track log services.
- m_logger.setSystemBundleContext(getBundleContext());
+ m_logger.setSystemBundleContext(_getBundleContext());
}
}
finally
@@ -1712,7 +1754,7 @@
if (bundle.getActivator() != null)
{
m_secureAction.startActivator(
- bundle.getActivator(), bundle.getBundleContext());
+ bundle.getActivator(), bundle._getBundleContext());
}
setBundleStateAndNotify(bundle, Bundle.ACTIVE);
@@ -1742,7 +1784,7 @@
m_dispatcher.removeListeners(bundle);
// Clean up the bundle context.
- ((BundleContextImpl) bundle.getBundleContext()).invalidate();
+ ((BundleContextImpl) bundle._getBundleContext()).invalidate();
bundle.setBundleContext(null);
// The spec says to expect BundleException or
@@ -1751,10 +1793,6 @@
{
throw (BundleException) th;
}
- else if (th instanceof SecurityException)
- {
- throw (SecurityException) th;
- }
else if ((System.getSecurityManager() != null) &&
(th instanceof java.security.PrivilegedActionException))
{
@@ -1969,13 +2007,14 @@
// If update failed, rethrow exception.
if (rethrow != null)
{
- if ((System.getSecurityManager() != null) &&
- (rethrow instanceof SecurityException))
+ if (rethrow instanceof AccessControlException)
{
- throw (SecurityException) rethrow;
+ throw (AccessControlException) rethrow;
}
-
- throw new BundleException("Update of bundle " + bundle + " failed.", rethrow);
+ else
+ {
+ throw new BundleException("Update of bundle " + bundle + " failed.", rethrow);
+ }
}
}
finally
@@ -2082,7 +2121,7 @@
{
if (bundle.getActivator() != null)
{
- m_secureAction.stopActivator(bundle.getActivator(), bundle.getBundleContext());
+ m_secureAction.stopActivator(bundle.getActivator(), bundle._getBundleContext());
}
}
catch (Throwable th)
@@ -2110,7 +2149,7 @@
m_dispatcher.removeListeners(bundle);
// Clean up the bundle context.
- ((BundleContextImpl) bundle.getBundleContext()).invalidate();
+ ((BundleContextImpl) bundle._getBundleContext()).invalidate();
bundle.setBundleContext(null);
setBundleStateAndNotify(bundle, Bundle.RESOLVED);
@@ -2128,10 +2167,6 @@
{
throw (BundleException) rethrow;
}
- else if (rethrow instanceof SecurityException)
- {
- throw (SecurityException) rethrow;
- }
else if ((System.getSecurityManager() != null) &&
(rethrow instanceof java.security.PrivilegedActionException))
{
@@ -2197,7 +2232,7 @@
BundleImpl target = null;
synchronized (m_installedBundleLock_Priority2)
{
- target = (BundleImpl) m_installedBundleMap.remove(bundle.getLocation());
+ target = (BundleImpl) m_installedBundleMap.remove(bundle._getLocation());
m_installedBundleIndex.remove(new Long(target.getBundleId()));
}
@@ -2431,18 +2466,14 @@
}
}
- if ((System.getSecurityManager() != null) &&
- (ex instanceof SecurityException))
- {
- throw (SecurityException) ex;
- }
-
- ex.printStackTrace();
-
if (ex instanceof BundleException)
{
throw (BundleException) ex;
}
+ else if (ex instanceof AccessControlException)
+ {
+ throw (AccessControlException) ex;
+ }
else
{
throw new BundleException("Could not create bundle object.", ex);
@@ -2595,7 +2626,7 @@
if (oldFilter != null)
{
final Collection removed = Collections.singleton(
- new ListenerHookInfoImpl(bundle.getBundleContext(), l, oldFilter.toString(), true));
+ new ListenerHookInfoImpl(((BundleImpl) bundle)._getBundleContext(), l, oldFilter.toString(), true));
InvokeHookCallback removedCallback = new ListenerHookRemovedCallback(removed);
for (int i = 0; i < listenerHooks.size(); i++)
{
@@ -2605,7 +2636,7 @@
// Invoke the ListenerHook.added() on all hooks.
final Collection added = Collections.singleton(
- new ListenerHookInfoImpl(bundle.getBundleContext(), l, f, false));
+ new ListenerHookInfoImpl(((BundleImpl) bundle)._getBundleContext(), l, f, false));
InvokeHookCallback addedCallback = new InvokeHookCallback()
{
public void invokeHook(Object hook)
@@ -2802,7 +2833,7 @@
{
public void invokeHook(Object hook)
{
- ((FindHook) hook).find(bundle.getBundleContext(),
+ ((FindHook) hook).find(bundle._getBundleContext(),
className,
expr,
!checkAssignable,
@@ -2851,26 +2882,14 @@
for (int i = 0; i < refs.length; i++)
{
- String[] objectClass = (String[]) refs[i].getProperty(Constants.OBJECTCLASS);
-
- if (objectClass == null)
+ try
{
- continue;
+ ((SecurityManager) sm).checkPermission(new ServicePermission(refs[i], ServicePermission.GET));
+ result.add(refs[i]);
}
-
- for (int j = 0; j < objectClass.length; j++)
+ catch (Exception ex)
{
- try
- {
- ((SecurityManager) sm).checkPermission(new ServicePermission(
- objectClass[j], ServicePermission.GET));
- result.add(refs[i]);
- break;
- }
- catch (Exception ex)
- {
- // Ignore, since we are just testing permission.
- }
+ // Ignore, since we are just testing permission.
}
}
@@ -2972,7 +2991,7 @@
new Requirement(
ICapability.PACKAGE_NAMESPACE,
null,
- new R4Attribute[] { new R4Attribute(ICapability.PACKAGE_PROPERTY, pkgName, false) }));
+ new R4Attribute[] { new R4Attribute(ICapability.PACKAGE_PROPERTY, pkgName, false) }), null);
if (exports != null)
{
@@ -3104,7 +3123,7 @@
new Requirement(
ICapability.PACKAGE_NAMESPACE,
null,
- new R4Attribute[] { new R4Attribute(ICapability.PACKAGE_PROPERTY, ((Capability) caps[capIdx]).getPackageName(), false) }));
+ new R4Attribute[] { new R4Attribute(ICapability.PACKAGE_PROPERTY, ((Capability) caps[capIdx]).getPackageName(), false) }), null);
// Search through the current providers to find the target module.
for (int i = 0; (resolvedCaps != null) && (i < resolvedCaps.size()); i++)
@@ -3184,12 +3203,7 @@
}
// Return the results.
- if (list.size() > 0)
- {
- return (Bundle[]) list.toArray(new Bundle[list.size()]);
- }
-
- return null;
+ return (Bundle[]) list.toArray(new Bundle[list.size()]);
}
boolean resolveBundles(Bundle[] targets)
@@ -3489,13 +3503,13 @@
m_securityProvider = securityProvider;
}
- Object getSignerMatcher(BundleImpl bundle)
+ Object getSignerMatcher(BundleImpl bundle, int signersType)
{
if ((bundle != this) && (m_securityProvider != null))
{
- return m_securityProvider.getSignerMatcher(bundle);
+ return m_securityProvider.getSignerMatcher(bundle, signersType);
}
- return null;
+ return new HashMap();
}
boolean impliesBundlePermission(BundleProtectionDomain bundleProtectionDomain, Permission permission, boolean direct)
@@ -3820,55 +3834,6 @@
return;
}
- // If a security manager is installed, then check for permission
- // to import the necessary packages.
- if (System.getSecurityManager() != null)
- {
- BundleProtectionDomain pd = (BundleProtectionDomain)
- bundle.getProtectionDomain();
-
-/*
- TODO: SECURITY - We need to fix this import check by looking at the wire
- associated with it, not the import since we don't know the
- package name associated with the import since it is a filter.
-
- IRequirement[] imports = bundle.getInfo().getCurrentModule().getRequirements();
- for (int i = 0; i < imports.length; i++)
- {
- if (imports[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
- {
- PackagePermission perm = new PackagePermission(
- imports[i].???,
- PackagePermission.IMPORT);
-
- if (!pd.impliesDirect(perm))
- {
- throw new java.security.AccessControlException(
- "PackagePermission.IMPORT denied for import: " +
- imports[i].getName(), perm);
- }
- }
- }
-*/
- // Check export permission for all exports of the current module.
- ICapability[] exports = rootModule.getCapabilities();
- for (int i = 0; i < exports.length; i++)
- {
- if (exports[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
- {
- PackagePermission perm = new PackagePermission(
- (String) exports[i].getProperties().get(ICapability.PACKAGE_PROPERTY), PackagePermission.EXPORT);
-
- if (!pd.impliesDirect(perm))
- {
- throw new java.security.AccessControlException(
- "PackagePermission.EXPORT denied for export: " +
- exports[i].getProperties().get(ICapability.PACKAGE_PROPERTY), perm);
- }
- }
- }
- }
-
// If the root module to resolve is a fragment, then we
// must find a host to attach it to and resolve the host
// instead, since the underlying resolver doesn't know
@@ -3966,14 +3931,14 @@
return candidateWire;
}
- public synchronized List getResolvedCandidates(IRequirement req)
+ public synchronized List getResolvedCandidates(IRequirement req, IModule reqModule)
{
- return m_resolverState.getResolvedCandidates(req);
+ return m_resolverState.getResolvedCandidates(req, reqModule);
}
- public synchronized List getUnresolvedCandidates(IRequirement req)
+ public synchronized List getUnresolvedCandidates(IRequirement req, IModule reqModule)
{
- return m_resolverState.getUnresolvedCandidates(req);
+ return m_resolverState.getUnresolvedCandidates(req, reqModule);
}
private void markResolvedModules(Map resolvedModuleWireMap)
@@ -4185,7 +4150,7 @@
try
{
Felix.m_secureAction.stopActivator((BundleActivator)
- m_activatorList.get(i), getBundleContext());
+ m_activatorList.get(i), _getBundleContext());
}
catch (Throwable throwable)
{
@@ -4196,6 +4161,12 @@
}
}
+ if (m_securityManager != null)
+ {
+ System.setSecurityManager(null);
+ m_securityManager = null;
+ }
+
if (m_extensionManager != null)
{
m_extensionManager.removeExtensions(Felix.this);
@@ -4206,7 +4177,7 @@
try
{
// Clean up the bundle context.
- ((BundleContextImpl) getBundleContext()).invalidate();
+ ((BundleContextImpl) _getBundleContext()).invalidate();
setBundleContext(null);
// Set the framework state to resolved and open
@@ -4618,4 +4589,4 @@
{
return m_urlHandlersActivator.getContentHandlerService(mimeType);
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/main/java/org/apache/felix/framework/FelixResolverState.java b/framework/src/main/java/org/apache/felix/framework/FelixResolverState.java
index d563538..e904628 100644
--- a/framework/src/main/java/org/apache/felix/framework/FelixResolverState.java
+++ b/framework/src/main/java/org/apache/felix/framework/FelixResolverState.java
@@ -18,6 +18,7 @@
*/
package org.apache.felix.framework;
+import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -35,6 +36,7 @@
import org.apache.felix.moduleloader.IModule;
import org.apache.felix.moduleloader.IRequirement;
import org.apache.felix.moduleloader.IWire;
+import org.osgi.framework.BundlePermission;
import org.osgi.framework.Constants;
import org.osgi.framework.PackagePermission;
import org.osgi.framework.Version;
@@ -294,6 +296,15 @@
// Create a list of all matching hosts for this fragment.
List matchingHosts = new ArrayList();
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ {
+ if (!((BundleProtectionDomain) fragment.getSecurityContext()).impliesDirect(new BundlePermission(
+ fragment.getSymbolicName(), BundlePermission.FRAGMENT)))
+ {
+ return matchingHosts;
+ }
+ }
for (int hostIdx = 0; (hostReq != null) && (hostIdx < m_moduleList.size()); hostIdx++)
{
IModule host = (IModule) m_moduleList.get(hostIdx);
@@ -315,6 +326,15 @@
{
continue;
}
+
+ if (sm != null)
+ {
+ if (!((BundleProtectionDomain) host.getSecurityContext()).impliesDirect(new BundlePermission(host.getSymbolicName(),
+ BundlePermission.HOST)))
+ {
+ continue;
+ }
+ }
matchingHosts.add(hostCap);
}
@@ -633,6 +653,14 @@
// If we have a host capability, then loop through all fragments trying to
// find ones that match.
List fragmentList = new ArrayList();
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ {
+ if (!((BundleProtectionDomain) host.getSecurityContext()).impliesDirect(new BundlePermission(host.getSymbolicName(), BundlePermission.HOST)))
+ {
+ return fragmentList;
+ }
+ }
for (Iterator it = m_fragmentMap.entrySet().iterator(); (hostCap != null) && it.hasNext(); )
{
Map.Entry entry = (Map.Entry) it.next();
@@ -652,7 +680,14 @@
{
continue;
}
-
+
+ if (sm != null)
+ {
+ if (!((BundleProtectionDomain) fragment.getSecurityContext()).impliesDirect(new BundlePermission(fragment.getSymbolicName(), BundlePermission.FRAGMENT)))
+ {
+ continue;
+ }
+ }
IRequirement hostReq = getFragmentHostRequirement(fragment);
// If we have a host requirement, then loop through each host and
@@ -880,7 +915,7 @@
//dumpPackageIndex(m_resolvedPkgIndex);
}
- public synchronized List getResolvedCandidates(IRequirement req)
+ public synchronized List getResolvedCandidates(IRequirement req, IModule reqModule)
{
// Synchronized on the module manager to make sure that no
// modules are added, removed, or resolved.
@@ -896,20 +931,24 @@
ICapability cap = (ICapability) capList.get(capIdx);
if (req.isSatisfied(cap))
{
-// TODO: RB - Is this permission check correct.
- if ((System.getSecurityManager() != null) &&
- !((BundleProtectionDomain) cap.getModule().getSecurityContext())
- .impliesDirect(new PackagePermission(pkgName, PackagePermission.EXPORT)))
+ if (System.getSecurityManager() != null)
{
- m_logger.log(Logger.LOG_DEBUG,
- "PackagePermission.EXPORT denied for "
- + pkgName
- + "from " + cap.getModule().getId());
+ if (reqModule != ((ICapability) capList.get(capIdx)).getModule())
+ {
+ if ((!((BundleProtectionDomain)((ICapability)
+ capList.get(capIdx)).getModule().getSecurityContext()).impliesDirect(
+ new PackagePermission(((Requirement) req).getTargetName(), PackagePermission.EXPORTONLY))) ||
+ !((reqModule == null) ||
+ ((BundleProtectionDomain) reqModule.getSecurityContext()).impliesDirect(
+ new PackagePermission(((Requirement) req).getTargetName(), ((ICapability)
+ capList.get(capIdx)).getModule().getBundle(),PackagePermission.IMPORT))
+ ))
+ {
+ continue;
+ }
+ }
}
- else
- {
- candidates.add(cap);
- }
+ candidates.add(cap);
}
}
}
@@ -926,23 +965,33 @@
ICapability cap = (ICapability) caps.get(capIdx);
if (req.isSatisfied(cap))
{
-// TODO: RB - Is this permission check correct.
- if (cap.getNamespace().equals(ICapability.PACKAGE_NAMESPACE) &&
- (System.getSecurityManager() != null) &&
- !((BundleProtectionDomain) module.getSecurityContext()).impliesDirect(
- new PackagePermission(
- (String) cap.getProperties().get(ICapability.PACKAGE_PROPERTY),
- PackagePermission.EXPORT)))
+ if (System.getSecurityManager() != null)
{
- m_logger.log(Logger.LOG_DEBUG,
- "PackagePermission.EXPORT denied for "
- + cap.getProperties().get(ICapability.PACKAGE_PROPERTY)
- + "from " + module.getId());
+ if (req.getNamespace().equals(ICapability.PACKAGE_NAMESPACE) && (
+ !((BundleProtectionDomain) cap.getModule().getSecurityContext()).impliesDirect(
+ new PackagePermission((String) cap.getProperties().get(ICapability.PACKAGE_PROPERTY), PackagePermission.EXPORTONLY)) ||
+ !((reqModule == null) ||
+ ((BundleProtectionDomain) reqModule.getSecurityContext()).impliesDirect(
+ new PackagePermission((String) cap.getProperties().get(ICapability.PACKAGE_PROPERTY), cap.getModule().getBundle(),PackagePermission.IMPORT))
+ )))
+ {
+ if (reqModule != cap.getModule())
+ {
+ continue;
+ }
+ }
+ if (req.getNamespace().equals(ICapability.MODULE_NAMESPACE) && (
+ !((BundleProtectionDomain) cap.getModule().getSecurityContext()).impliesDirect(
+ new BundlePermission(cap.getModule().getSymbolicName(), BundlePermission.PROVIDE)) ||
+ !((reqModule == null) ||
+ ((BundleProtectionDomain) reqModule.getSecurityContext()).impliesDirect(
+ new BundlePermission(reqModule.getSymbolicName(), BundlePermission.REQUIRE))
+ )))
+ {
+ continue;
+ }
}
- else
- {
- candidates.add(cap);
- }
+ candidates.add(cap);
}
}
}
@@ -951,7 +1000,7 @@
return candidates;
}
- public synchronized List getUnresolvedCandidates(IRequirement req)
+ public synchronized List getUnresolvedCandidates(IRequirement req, IModule reqModule)
{
// Get all matching unresolved capabilities.
List candidates = new ArrayList();
@@ -965,6 +1014,23 @@
// the unresolved candidate to the list.
if (req.isSatisfied((ICapability) capList.get(capIdx)))
{
+ if (System.getSecurityManager() != null)
+ {
+ if (reqModule != ((ICapability) capList.get(capIdx)).getModule())
+ {
+ if (!((BundleProtectionDomain)((ICapability)
+ capList.get(capIdx)).getModule().getSecurityContext()).impliesDirect(
+ new PackagePermission(((Requirement) req).getTargetName(), PackagePermission.EXPORTONLY)) ||
+ !((reqModule == null) ||
+ ((BundleProtectionDomain) reqModule.getSecurityContext()).impliesDirect(
+ new PackagePermission(((Requirement) req).getTargetName(), ((ICapability)
+ capList.get(capIdx)).getModule().getBundle(),PackagePermission.IMPORT))
+ ))
+ {
+ continue;
+ }
+ }
+ }
candidates.add(capList.get(capIdx));
}
}
@@ -980,6 +1046,32 @@
// the unresolved candidate to the list.
if ((cap != null) && !modules[modIdx].isResolved())
{
+ if (System.getSecurityManager() != null)
+ {
+ if (req.getNamespace().equals(ICapability.PACKAGE_NAMESPACE) && (
+ !((BundleProtectionDomain) cap.getModule().getSecurityContext()).impliesDirect(
+ new PackagePermission((String) cap.getProperties().get(ICapability.PACKAGE_PROPERTY), PackagePermission.EXPORTONLY)) ||
+ !((reqModule == null) ||
+ ((BundleProtectionDomain) reqModule.getSecurityContext()).impliesDirect(
+ new PackagePermission((String) cap.getProperties().get(ICapability.PACKAGE_PROPERTY), cap.getModule().getBundle(),PackagePermission.IMPORT))
+ )))
+ {
+ if (reqModule != cap.getModule())
+ {
+ continue;
+ }
+ }
+ if (req.getNamespace().equals(ICapability.MODULE_NAMESPACE) && (
+ !((BundleProtectionDomain) cap.getModule().getSecurityContext()).impliesDirect(
+ new BundlePermission(cap.getModule().getSymbolicName(), BundlePermission.PROVIDE)) ||
+ !((reqModule == null) ||
+ ((BundleProtectionDomain) reqModule.getSecurityContext()).impliesDirect(
+ new BundlePermission(reqModule.getSymbolicName(), BundlePermission.REQUIRE))
+ )))
+ {
+ continue;
+ }
+ }
candidates.add(cap);
}
}
diff --git a/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java b/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java
index 2355fbe..914bff1 100644
--- a/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java
@@ -2102,9 +2102,9 @@
{
// Try to see if there is an exporter available.
List exports =
- resolver.getResolvedCandidates(pkgReq);
+ resolver.getResolvedCandidates(pkgReq, module);
exports = (exports.size() == 0)
- ? resolver.getUnresolvedCandidates(pkgReq)
+ ? resolver.getUnresolvedCandidates(pkgReq, module)
: exports;
// An exporter might be available, but it may have attributes
@@ -2117,9 +2117,9 @@
{
IRequirement req = new Requirement(
ICapability.PACKAGE_NAMESPACE, "(package=" + pkgName + ")");
- exports = resolver.getResolvedCandidates(req);
+ exports = resolver.getResolvedCandidates(req, module);
exports = (exports.size() == 0)
- ? resolver.getUnresolvedCandidates(req)
+ ? resolver.getUnresolvedCandidates(req, module)
: exports;
}
catch (InvalidSyntaxException ex)
@@ -2163,9 +2163,9 @@
// This should never happen.
}
List exports =
- resolver.getResolvedCandidates(pkgReq);
+ resolver.getResolvedCandidates(pkgReq, module);
exports = (exports.size() == 0)
- ? resolver.getUnresolvedCandidates(pkgReq)
+ ? resolver.getUnresolvedCandidates(pkgReq, module)
: exports;
if (exports.size() > 0)
{
diff --git a/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java b/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java
index 1a5a9fe..4f8cfad 100644
--- a/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java
@@ -246,7 +246,7 @@
* @param bundles array of bundles to refresh or <tt>null</tt> to refresh
* any bundles in need of refreshing.
**/
- public synchronized void refreshPackages(Bundle[] bundles)
+ public void refreshPackages(Bundle[] bundles)
throws SecurityException
{
Object sm = System.getSecurityManager();
@@ -256,21 +256,23 @@
((SecurityManager) sm).checkPermission(
new AdminPermission(m_systemBundle, AdminPermission.RESOLVE));
}
-
- // Save our request parameters and notify all.
- if (m_reqBundles == null)
+ synchronized (this)
{
- m_reqBundles = new Bundle[][] { bundles };
+ // Save our request parameters and notify all.
+ if (m_reqBundles == null)
+ {
+ m_reqBundles = new Bundle[][] { bundles };
+ }
+ else
+ {
+ Bundle[][] newReqBundles = new Bundle[m_reqBundles.length + 1][];
+ System.arraycopy(m_reqBundles, 0,
+ newReqBundles, 0, m_reqBundles.length);
+ newReqBundles[m_reqBundles.length] = bundles;
+ m_reqBundles = newReqBundles;
+ }
+ notifyAll();
}
- else
- {
- Bundle[][] newReqBundles = new Bundle[m_reqBundles.length + 1][];
- System.arraycopy(m_reqBundles, 0,
- newReqBundles, 0, m_reqBundles.length);
- newReqBundles[m_reqBundles.length] = bundles;
- m_reqBundles = newReqBundles;
- }
- notifyAll();
}
public boolean resolveBundles(Bundle[] bundles)
diff --git a/framework/src/main/java/org/apache/felix/framework/StartLevelImpl.java b/framework/src/main/java/org/apache/felix/framework/StartLevelImpl.java
index 050f67e..c15bdb7 100644
--- a/framework/src/main/java/org/apache/felix/framework/StartLevelImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/StartLevelImpl.java
@@ -157,7 +157,7 @@
if (sm != null)
{
((SecurityManager) sm).checkPermission(
- new AdminPermission(bundle, AdminPermission.STARTLEVEL));
+ new AdminPermission(bundle, AdminPermission.EXECUTE));
}
if (bundle.getBundleId() == 0)
diff --git a/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleStreamHandler.java b/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleStreamHandler.java
index bcfd010..0f6a5d7 100644
--- a/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleStreamHandler.java
+++ b/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleStreamHandler.java
@@ -23,6 +23,9 @@
import java.net.*;
import org.apache.felix.framework.util.SecureAction;
+import org.apache.felix.framework.util.Util;
+import org.osgi.framework.AdminPermission;
+import org.osgi.framework.Bundle;
class URLHandlersBundleStreamHandler extends URLStreamHandler
{
@@ -43,6 +46,10 @@
protected synchronized URLConnection openConnection(URL url) throws IOException
{
+ if (!"felix".equals(url.getAuthority()))
+ {
+ checkPermission(url);
+ }
if (m_framework != null)
{
return new URLHandlersBundleURLConnection(url, m_framework);
@@ -74,4 +81,44 @@
}
throw new IOException("No framework context found");
}
+
+ protected void parseURL(URL u, String spec, int start, int limit)
+ {
+ super.parseURL(u, spec, start, limit);
+
+ if (checkPermission(u))
+ {
+ super.setURL(u, u.getProtocol(), u.getHost(), u.getPort(), "felix", u.getUserInfo(), u.getPath(), u.getQuery(), u.getRef());
+ }
+ }
+
+ private boolean checkPermission(URL u)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ {
+ Object framework = m_framework;
+ if (framework == null)
+ {
+ framework = URLHandlers.getFrameworkFromContext();
+ if (!(framework instanceof Felix))
+ {
+ return false;
+ }
+ }
+ Felix felix = (Felix) framework;
+ long bundleId = Util.getBundleIdFromModuleId(u.getHost());
+ Bundle bundle = felix.getBundle(bundleId);
+ if (bundle != null)
+ {
+ sm.checkPermission(new AdminPermission(bundle, AdminPermission.RESOURCE));
+ return true;
+ }
+ }
+ else
+ {
+ return true;
+ }
+ return false;
+ }
}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/cache/JarRevision.java b/framework/src/main/java/org/apache/felix/framework/cache/JarRevision.java
index 6377241..b12a38c 100644
--- a/framework/src/main/java/org/apache/felix/framework/cache/JarRevision.java
+++ b/framework/src/main/java/org/apache/felix/framework/cache/JarRevision.java
@@ -144,7 +144,7 @@
{
// Do it the manual way to have a chance to
// set request properties such as proxy auth.
- URL url = new URL(getLocation());
+ URL url = BundleCache.getSecureAction().createURL(null, getLocation(), null);
URLConnection conn = url.openConnection();
// Support for http proxy authentication.
diff --git a/framework/src/main/java/org/apache/felix/framework/ext/SecurityProvider.java b/framework/src/main/java/org/apache/felix/framework/ext/SecurityProvider.java
index b20e35b..2ae3c45 100644
--- a/framework/src/main/java/org/apache/felix/framework/ext/SecurityProvider.java
+++ b/framework/src/main/java/org/apache/felix/framework/ext/SecurityProvider.java
@@ -27,7 +27,7 @@
{
boolean hasBundlePermission(ProtectionDomain pd, Permission p, boolean direct);
- Object getSignerMatcher(Bundle bundle);
+ Object getSignerMatcher(Bundle bundle, int signersType);
void checkBundle(Bundle bundle) throws Exception;
}
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java
index 606c342..eb42f0c 100644
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java
+++ b/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java
@@ -157,8 +157,8 @@
{
// Get "resolved" and "unresolved" candidates and put
// the "resolved" candidates first.
- List candidates = state.getResolvedCandidates(target);
- candidates.addAll(state.getUnresolvedCandidates(target));
+ List candidates = state.getResolvedCandidates(target, importer);
+ candidates.addAll(state.getUnresolvedCandidates(target, importer));
// Take the first candidate that can resolve.
for (int candIdx = 0;
@@ -381,8 +381,8 @@
// package maps. The "resolved" candidates have higher priority
// than "unresolved" ones, so put the "resolved" candidates
// at the front of the list of candidates.
- List candidates = state.getResolvedCandidates(reqs[reqIdx]);
- candidates.addAll(state.getUnresolvedCandidates(reqs[reqIdx]));
+ List candidates = state.getResolvedCandidates(reqs[reqIdx], targetModule);
+ candidates.addAll(state.getUnresolvedCandidates(reqs[reqIdx], targetModule));
// If we have candidates, then we need to recursively populate
// the resolver map with each of them.
@@ -1731,7 +1731,7 @@
public static interface ResolverState
{
IModule[] getModules();
- List getResolvedCandidates(IRequirement req);
- List getUnresolvedCandidates(IRequirement req);
+ List getResolvedCandidates(IRequirement req, IModule reqModule);
+ List getUnresolvedCandidates(IRequirement req, IModule reqModule);
}
}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java b/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
index 4d45b5d..2df2a79 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
@@ -819,89 +819,75 @@
// one of the service interfaces; the objectClass property
// of the service stores its service interfaces.
ServiceReference ref = ((ServiceEvent) event).getServiceReference();
- String[] objectClass = (String[]) ref.getProperty(Constants.OBJECTCLASS);
- // On the safe side, if there is no objectClass property
- // then ignore event altogether.
- if (objectClass != null)
+ boolean hasPermission = true;
+ Object sm = System.getSecurityManager();
+ if ((acc != null) && (sm != null))
{
- boolean hasPermission = false;
-
- Object sm = System.getSecurityManager();
- if ((acc != null) && (sm != null))
+ try
{
- for (int i = 0;
- !hasPermission && (i < objectClass.length);
- i++)
+ ServicePermission perm =
+ new ServicePermission(
+ ref, ServicePermission.GET);
+ ((SecurityManager) sm).checkPermission(perm, acc);
+ }
+ catch (Exception ex)
+ {
+ hasPermission = false;
+ }
+ }
+
+ if (hasPermission)
+ {
+ // Dispatch according to the filter.
+ boolean matched = (filter == null)
+ || filter.match(((ServiceEvent) event).getServiceReference());
+
+ if (matched)
+ {
+ if ((l instanceof AllServiceListener) ||
+ Util.isServiceAssignable(bundle, ((ServiceEvent) event).getServiceReference()))
{
- try
+ if (System.getSecurityManager() != null)
{
- ServicePermission perm =
- new ServicePermission(
- objectClass[i], ServicePermission.GET);
- ((SecurityManager) sm).checkPermission(perm, acc);
- hasPermission = true;
+ AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ ((ServiceListener) l).serviceChanged((ServiceEvent) event);
+ return null;
+ }
+ });
}
- catch (Exception ex)
+ else
{
+ ((ServiceListener) l).serviceChanged((ServiceEvent) event);
}
}
}
- else
+ // We need to send an MODIFIED_ENDMATCH event if the listener
+ // matched previously.
+ else if (((ServiceEvent) event).getType() == ServiceEvent.MODIFIED)
{
- hasPermission = true;
- }
-
- if (hasPermission)
- {
- // Dispatch according to the filter.
- boolean matched = (filter == null)
- || filter.match(((ServiceEvent) event).getServiceReference());
-
- if (matched)
+ if (filter.match(oldProps))
{
- if ((l instanceof AllServiceListener) ||
- Util.isServiceAssignable(bundle, ((ServiceEvent) event).getServiceReference()))
+ final ServiceEvent se = new ServiceEvent(
+ ServiceEvent.MODIFIED_ENDMATCH,
+ ((ServiceEvent) event).getServiceReference());
+ if (System.getSecurityManager() != null)
{
- if (System.getSecurityManager() != null)
+ AccessController.doPrivileged(new PrivilegedAction()
{
- AccessController.doPrivileged(new PrivilegedAction() {
- public Object run()
- {
- ((ServiceListener) l).serviceChanged((ServiceEvent) event);
- return null;
- }
- });
- }
- else
- {
- ((ServiceListener) l).serviceChanged((ServiceEvent) event);
- }
+ public Object run()
+ {
+ ((ServiceListener) l).serviceChanged(se);
+ return null;
+ }
+ });
}
- }
- // We need to send an MODIFIED_ENDMATCH event if the listener
- // matched previously.
- else if (((ServiceEvent) event).getType() == ServiceEvent.MODIFIED)
- {
- if (filter.match(oldProps))
+ else
{
- final ServiceEvent se = new ServiceEvent(
- ServiceEvent.MODIFIED_ENDMATCH,
- ((ServiceEvent) event).getServiceReference());
- if (System.getSecurityManager() != null)
- {
- AccessController.doPrivileged(new PrivilegedAction() {
- public Object run()
- {
- ((ServiceListener) l).serviceChanged(se);
- return null;
- }
- });
- }
- else
- {
- ((ServiceListener) l).serviceChanged(se);
- }
+ ((ServiceListener) l).serviceChanged(se);
}
}
}