2004-07-24 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / bus / services.c
index ae7b783..81e3eaf 100644 (file)
@@ -31,6 +31,8 @@
 #include "utils.h"
 #include "activation.h"
 #include "policy.h"
+#include "bus.h"
+#include "selinux.h"
 
 struct BusService
 {
@@ -51,6 +53,8 @@ struct BusRegistry
   
   DBusHashTable *service_hash;
   DBusMemPool   *service_pool;
+
+  DBusHashTable *service_sid_table;
 };
 
 BusRegistry*
@@ -75,6 +79,8 @@ bus_registry_new (BusContext *context)
   if (registry->service_pool == NULL)
     goto failed;
 
+  registry->service_sid_table = NULL;
+  
   return registry;
 
  failed:
@@ -103,7 +109,9 @@ bus_registry_unref  (BusRegistry *registry)
         _dbus_hash_table_unref (registry->service_hash);
       if (registry->service_pool)
         _dbus_mem_pool_free (registry->service_pool);
-
+      if (registry->service_sid_table)
+        _dbus_hash_table_unref (registry->service_sid_table);
+      
       dbus_free (registry);
     }
 }
@@ -262,6 +270,8 @@ bus_registry_acquire_service (BusRegistry      *registry,
   DBusConnection *current_owner;
   BusClientPolicy *policy;
   BusService *service;
+  BusActivation  *activation;
+  BusSELinuxID *sid;
   
   retval = FALSE;
 
@@ -291,6 +301,24 @@ bus_registry_acquire_service (BusRegistry      *registry,
   policy = bus_connection_get_policy (connection);
   _dbus_assert (policy != NULL);
 
+  /* Note that if sid is #NULL then the bus's own context gets used
+   * in bus_connection_selinux_allows_acquire_service()
+   */
+  sid = bus_selinux_id_table_lookup (registry->service_sid_table,
+                                     service_name);
+
+  if (!bus_selinux_allows_acquire_service (connection, sid))
+    {
+      dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
+                      "Connection \"%s\" is not allowed to own the service \"%s\" due "
+                      "to SELinux policy",
+                      bus_connection_is_active (connection) ?
+                      bus_connection_get_name (connection) :
+                      "(inactive)",
+                     service_name);
+      goto out;
+    }
+      
   if (!bus_client_policy_check_can_own (policy, connection,
                                         service_name))
     {
@@ -376,12 +404,29 @@ bus_registry_acquire_service (BusRegistry      *registry,
       *result = DBUS_SERVICE_REPLY_PRIMARY_OWNER;
     }
 
-  retval = TRUE;
+  activation = bus_context_get_activation (registry->context);
+  retval = bus_activation_send_pending_auto_activation_messages (activation,
+                                                                service,
+                                                                transaction,
+                                                                error);
   
  out:
   return retval;
 }
 
+void
+bus_registry_set_service_sid_table (BusRegistry   *registry,
+                                    DBusHashTable *table)
+{
+  _dbus_assert (registry->service_sid_table != table);
+  
+  if (registry->service_sid_table)
+    _dbus_hash_table_unref (registry->service_sid_table);
+
+  registry->service_sid_table = table;
+  _dbus_hash_table_ref (table);
+}
+
 static void
 bus_service_unlink_owner (BusService      *service,
                           DBusConnection  *owner)
@@ -688,10 +733,9 @@ bus_service_remove_owner (BusService     *service,
   else
     {
       DBusList *link;
-      link = _dbus_list_get_first (&service->owners);
+      link = _dbus_list_get_first_link (&service->owners);
       _dbus_assert (link != NULL);
       link = _dbus_list_get_next_link (&service->owners, link);
-
       _dbus_assert (link != NULL);
 
       /* This will be our new owner */