FELIX-1827 Check permission to get and register services on behalf
of the component providing bundle

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@831005 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
index f10db78..e305094 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
@@ -18,6 +18,7 @@
  */
 package org.apache.felix.scr.impl.manager;
 
+import java.security.Permission;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Dictionary;
@@ -34,6 +35,7 @@
 import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServicePermission;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.component.ComponentConstants;
@@ -519,10 +521,40 @@
         } );
     }
 
-    public String toString() {
+
+    public String toString()
+    {
         return "Component: " + getName() + " (" + getId() + ")";
     }
 
+
+    private boolean hasServiceRegistrationPermissions()
+    {
+        boolean allowed = true;
+        if ( System.getSecurityManager() != null )
+        {
+            final String[] services = getComponentMetadata().getServiceMetadata().getProvides();
+            if ( services != null && services.length > 0 )
+            {
+                final Bundle bundle = getBundle();
+                for ( int i = 0; i < services.length; i++ )
+                {
+                    final Permission perm = new ServicePermission( services[i], ServicePermission.REGISTER );
+                    if ( !bundle.hasPermission( perm ) )
+                    {
+                        log( LogService.LOG_INFO, "Permission to register service {0} is denied", new Object[]
+                            { services[i] }, null );
+                        allowed = false;
+                    }
+                }
+            }
+        }
+
+        // no security manager or no services to register
+        return allowed;
+    }
+
+
     private void loadDependencyManagers( ComponentMetadata metadata )
     {
         List depMgrList = new ArrayList();
@@ -563,15 +595,21 @@
         Iterator it = getDependencyManagers();
         while ( it.hasNext() )
         {
-            DependencyManager dm = (DependencyManager) it.next();
+            DependencyManager dm = ( DependencyManager ) it.next();
 
             // ensure the target filter is correctly set
             dm.setTargetFilter( properties );
 
-            // check whether the service is satisfied
-            if ( !dm.isSatisfied() )
+            if ( !dm.hasGetPermission() )
             {
-                // at least one dependency is not satisfied
+                // bundle has no service get permission
+                log( LogService.LOG_INFO, "No permission to get dependency: {0}", new Object[]
+                    { dm.getName() }, null );
+                satisfied = false;
+            }
+            else if ( !dm.isSatisfied() )
+            {
+                // bundle would have permission but there are not enough services
                 log( LogService.LOG_INFO, "Dependency not satisfied: {0}", new Object[]
                     { dm.getName() }, null );
                 satisfied = false;
@@ -926,6 +964,16 @@
                 return;
             }
 
+            // Before creating the implementation object, we are going to
+            // test that the bundle has enough permissions to register services
+            if ( !acm.hasServiceRegistrationPermissions() )
+            {
+                acm.log( LogService.LOG_INFO, "Component is not permitted to register all services, cannot activate",
+                    null );
+                acm.changeState( Unsatisfied.getInstance() );
+                return;
+            }
+
             // 1. Load the component implementation class
             // 2. Create the component instance and component context
             // 3. Bind the target services
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
index afb943a..1533833 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
@@ -19,6 +19,7 @@
 package org.apache.felix.scr.impl.manager;
 
 
+import java.security.Permission;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Dictionary;
@@ -36,6 +37,7 @@
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceEvent;
 import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServicePermission;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.component.ComponentConstants;
 import org.osgi.service.log.LogService;
@@ -460,19 +462,32 @@
      */
     void enable() throws InvalidSyntaxException
     {
-        // get the current number of registered services available
-        ServiceReference refs[] = getFrameworkServiceReferences();
-        m_size = ( refs == null ) ? 0 : refs.length;
+        if ( hasGetPermission() )
+        {
+            // get the current number of registered services available
+            ServiceReference refs[] = getFrameworkServiceReferences();
+            m_size = ( refs == null ) ? 0 : refs.length;
 
-        // register the service listener
-        String filterString = "(" + Constants.OBJECTCLASS + "=" + m_dependencyMetadata.getInterface() + ")";
-        m_componentManager.getActivator().getBundleContext().addServiceListener( this, filterString );
+            // register the service listener
+            String filterString = "(" + Constants.OBJECTCLASS + "=" + m_dependencyMetadata.getInterface() + ")";
+            m_componentManager.getActivator().getBundleContext().addServiceListener( this, filterString );
 
-        m_componentManager.log( LogService.LOG_DEBUG,
-            "Registered for service events, currently {0} service(s) match the filter", new Object[]
-                { new Integer( m_size ) }, null );
+            m_componentManager.log( LogService.LOG_DEBUG,
+                "Registered for service events, currently {0} service(s) match the filter", new Object[]
+                    { new Integer( m_size ) }, null );
+        }
+        else
+        {
+            // no services available
+            m_size = 0;
+
+            m_componentManager.log( LogService.LOG_DEBUG,
+                "Not registered for service events since the bundle has no permission to get service {0}", new Object[]
+                    { m_dependencyMetadata.getInterface() }, null );
+        }
     }
 
+
     /**
      * Disposes off this dependency manager by removing as a service listener
      * and ungetting all services, which are still kept in the list of our
@@ -536,17 +551,23 @@
 
     private ServiceReference[] getFrameworkServiceReferences( String targetFilter )
     {
-        try
+        if ( hasGetPermission() )
         {
-            return m_componentManager.getActivator().getBundleContext().getServiceReferences(
-                m_dependencyMetadata.getInterface(), targetFilter );
+            try
+            {
+                return m_componentManager.getActivator().getBundleContext().getServiceReferences(
+                    m_dependencyMetadata.getInterface(), targetFilter );
+            }
+            catch ( InvalidSyntaxException ise )
+            {
+                m_componentManager.log( LogService.LOG_ERROR, "Unexpected problem with filter ''{0}''", new Object[]
+                    { targetFilter }, ise );
+                return null;
+            }
         }
-        catch ( InvalidSyntaxException ise )
-        {
-            m_componentManager.log( LogService.LOG_ERROR, "Unexpected problem with filter ''{0}''", new Object[]
-                { targetFilter }, ise );
-            return null;
-        }
+
+        m_componentManager.log( LogService.LOG_DEBUG, "No permission to access the services", null );
+        return null;
     }
 
 
@@ -763,6 +784,23 @@
     }
 
 
+    /**
+     * Returns <code>true</code> if the component providing bundle has permission
+     * to get the service described by this reference.
+     */
+    public boolean hasGetPermission()
+    {
+        if ( System.getSecurityManager() != null )
+        {
+            Permission perm = new ServicePermission( getServiceName(), ServicePermission.GET );
+            return m_componentManager.getBundle().hasPermission( perm );
+        }
+
+        // no security manager, hence permission given
+        return true;
+    }
+
+
     boolean open( Object instance )
     {
         m_componentInstance = instance;