[lib-fix] moved dbus_connection_get_unix_user from daemon to library
[platform/upstream/dbus.git] / bus / services.c
index 9318eef..90a2f5f 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2003  Red Hat, Inc.
  * Copyright (C) 2003  CodeFactory AB
+ * Copyright (C) 2013  Samsung Electronics
  *
  * Licensed under the Academic Free License version 2.1
  * 
 #include <dbus/dbus-list.h>
 #include <dbus/dbus-mempool.h>
 #include <dbus/dbus-marshal-validate.h>
-#include <linux/types.h>
-#include <errno.h>
-#include <stdlib.h>
-
-
 #include "driver.h"
 #include "services.h"
 #include "connection.h"
 #include "policy.h"
 #include "bus.h"
 #include "selinux.h"
+
+#ifdef ENABLE_KDBUS_TRANSPORT
+#include <linux/types.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+
 #include "kdbus-d.h"
+#include "dbus/kdbus.h"
+#include "dbus/kdbus-common.h"
+#endif
 
 struct BusService
 {
@@ -60,6 +67,9 @@ struct BusOwner
 
   unsigned int allow_replacement : 1;
   unsigned int do_not_queue : 1;
+#ifdef ENABLE_KDBUS_TRANSPORT
+  unsigned int is_kdbus_starter : 1;
+#endif
 };
 
 struct BusRegistry
@@ -177,6 +187,7 @@ _bus_service_find_owner_link (BusService *service,
   return link;
 }
 
+#ifdef ENABLE_KDBUS_TRANSPORT
 static DBusConnection *
 _bus_service_find_owner_connection (BusService *service,
                                    const char* unique_name)
@@ -198,6 +209,7 @@ _bus_service_find_owner_connection (BusService *service,
 
   return NULL;
 }
+#endif
 
 static void
 bus_owner_set_flags (BusOwner *owner,
@@ -208,6 +220,11 @@ bus_owner_set_flags (BusOwner *owner,
 
    owner->do_not_queue =
         (flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) != FALSE;
+
+#ifdef ENABLE_KDBUS_TRANSPORT
+   owner->is_kdbus_starter =
+        (flags & KDBUS_NAME_STARTER_NAME) != FALSE;
+#endif
 }
 
 static BusOwner *
@@ -622,6 +639,7 @@ bus_registry_acquire_service (BusRegistry      *registry,
   return retval;
 }
 
+#ifdef ENABLE_KDBUS_TRANSPORT
 dbus_bool_t
 bus_registry_acquire_kdbus_service (BusRegistry      *registry,
                               DBusConnection   *connection,
@@ -633,12 +651,14 @@ bus_registry_acquire_kdbus_service (BusRegistry      *registry,
   dbus_bool_t retval;
   BusService *service;
   BusActivation  *activation;
-
   DBusString service_name_real;
   const DBusString *service_name = &service_name_real;
   char* name;
   dbus_uint32_t flags;
   __u64 sender_id;
+  const char* conn_unique_name;
+  DBusConnection* phantom;
+  unsigned long int uid;
 
   if (!dbus_message_get_args (message, error,
                               DBUS_TYPE_STRING, &name,
@@ -654,115 +674,117 @@ bus_registry_acquire_kdbus_service (BusRegistry      *registry,
                                 _dbus_string_get_length (service_name)))
     {
       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
-                      "Requested bus name \"%s\" is not valid",
-                      _dbus_string_get_const_data (service_name));
+                      "Requested bus name \"%s\" is not valid", name);
 
       _dbus_verbose ("Attempt to acquire invalid service name\n");
 
-      goto out;
+      return FALSE;
     }
 
   if (_dbus_string_get_byte (service_name, 0) == ':')
     {
       /* Not allowed; only base services can start with ':' */
       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
-                      "Cannot acquire a service starting with ':' such as \"%s\"",
-                      _dbus_string_get_const_data (service_name));
+                      "Cannot acquire a service starting with ':' such as \"%s\"", name);
 
-      _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"",
-                     _dbus_string_get_const_data (service_name));
+      _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"", name);
 
-      goto out;
+      return FALSE;
     }
 
+  conn_unique_name = dbus_message_get_sender(message);
+
   if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
     {
       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
                       "Connection \"%s\" is not allowed to own the service \"%s\"because "
                       "it is reserved for D-Bus' use only",
-                      bus_connection_is_active (connection) ?
-                      bus_connection_get_name (connection) :
-                      "(inactive)",
-                      DBUS_SERVICE_DBUS);
-      goto out;
+                      conn_unique_name, DBUS_SERVICE_DBUS);
+      return FALSE;
     }
 
-       service = bus_registry_lookup (registry, service_name);
-       if (service == NULL)
-       {
-               service = bus_registry_ensure (registry, service_name, connection, flags,
-                                                                        transaction, error);  //adds daemon to service owners list - must be removed after right owner is set
-               if (service == NULL)
-                 goto out;
+  sender_id = sender_name_to_id(conn_unique_name, error);
+  if(dbus_error_is_set(error))
+    return FALSE;
 
-               if(!kdbus_register_policy(service_name, connection))
-               {
-                       dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
-                                                 "Connection is not allowed to own the service \"%s\" due to security policies in the configuration file",
-                                                 _dbus_string_get_const_data (service_name));
-                       goto failed;
-               }
-       }
+  phantom = bus_connections_find_conn_by_name(bus_connection_get_connections(connection), conn_unique_name);
+  if(phantom == NULL)
+    {
+      phantom = create_phantom_connection(connection, conn_unique_name, error);
+      if(phantom == NULL)
+        return FALSE;
+    }
 
-       sender_id = sender_name_to_id(dbus_message_get_sender(message), error);
-       if(dbus_error_is_set(error))
-               goto failed;
+  if (!bus_client_policy_check_can_own (bus_connection_get_policy (phantom), service_name))
+    {
+      dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
+          "Connection \"%s\" is not allowed to own the service \"%s\" due "
+          "to security policies in the configuration file", conn_unique_name, name);
+      goto failed;
+    }
 
-       *result = kdbus_request_name(connection, service_name, flags, sender_id);
-       if(*result == -EPERM)
-       {
-               dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
-                                         "Connection is not allowed to own the service \"%s\" due to security policies in the configuration file",
-                                         _dbus_string_get_const_data (service_name));
-               goto failed;
-       }
-       else if(*result < 0)
-       {
-               dbus_set_error (error, DBUS_ERROR_FAILED , "Name \"%s\" could not be acquired", name);
-               goto failed;
-       }
+  if (!kdbus_connection_get_unix_user(phantom, conn_unique_name, &uid, NULL))
+    goto failed;
 
-       if((*result == DBUS_REQUEST_NAME_REPLY_IN_QUEUE) || (*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER))
-       {
-           DBusConnection* phantom;
-           const char* name;
-
-           name = dbus_message_get_sender(message);
-           phantom = bus_connections_find_conn_by_name(bus_connection_get_connections(connection), name);
-        if(phantom == NULL)
-            phantom = create_phantom_connection(connection, name, error);
-           if(phantom == NULL)
-               goto failed2;
-           if (!bus_service_add_owner (service, phantom, flags, transaction, error))
-               goto failed2;
-           if(*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
-           {
-            /* Here we are removing DBus daemon as an owner of the service,
-             * which is set by bus_registry_ensure.
-             * If bus_service_remove_owner fail, we ignore it, because it has
-             * almost none impact on the usage
-             */
-               if(_bus_service_find_owner_link (service, connection))
-                bus_service_remove_owner (service, connection, transaction, NULL);
-           }
-       }
+#ifdef POLICY_TO_KDBUS
+  if (!register_kdbus_policy(name, dbus_connection_get_transport(phantom), uid))
+  {
+    dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
+            "Kdbus error when setting policy for connection \"%s\" and  service name \"%s\"",
+            conn_unique_name, name);
+    goto failed;
+  }
+#endif
 
-  activation = bus_context_get_activation (registry->context);
-  retval = bus_activation_send_pending_auto_activation_messages (activation,
-                                                                service,
-                                                                transaction,
-                                                                error);
- out:
-     return retval;
+  *result = kdbus_request_name(connection, service_name, flags, sender_id);
+  if(*result == -EPERM)
+    {
+      dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
+          "Kdbus not allowed %s to own the service \"%s\"",
+          conn_unique_name, _dbus_string_get_const_data (service_name));
+      goto failed;
+    }
+  else if(*result < 0)
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED , "Name \"%s\" could not be acquired", name);
+      goto failed;
+    }
+
+  if((*result == DBUS_REQUEST_NAME_REPLY_IN_QUEUE) || (*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER))
+    {
+      service = bus_registry_lookup (registry, service_name);
+      if (service == NULL)
+        {
+          service = bus_registry_ensure (registry, service_name, phantom, flags,
+                       transaction, error);
+          if (service == NULL)
+            goto failed2;
+        }
+      else
+        {
+          if (!bus_service_add_owner (service, phantom, flags, transaction, error))
+            goto failed2;
+        }
+
+      activation = bus_context_get_activation (registry->context);
+      retval = bus_activation_send_pending_auto_activation_messages (activation,
+                   service,
+                   transaction,
+                   error);
+    }
+  else
+    retval = TRUE;
+
+  return retval;
   
 failed2:
-    kdbus_release_name(connection, service_name, sender_id);
+  kdbus_release_name(phantom, service_name, sender_id);
 failed:
-    if(_bus_service_find_owner_link (service, connection))
-        bus_service_remove_owner (service, connection, transaction, NULL);
+  bus_connection_disconnected(phantom);
 
   return FALSE;
 }
+#endif
 
 dbus_bool_t
 bus_registry_release_service (BusRegistry      *registry,
@@ -841,6 +863,7 @@ bus_registry_release_service (BusRegistry      *registry,
   return retval;
 }
 
+#ifdef ENABLE_KDBUS_TRANSPORT
 dbus_bool_t
 bus_registry_release_service_kdbus (const char* sender_name,
                               DBusConnection   *connection,
@@ -927,6 +950,7 @@ bus_registry_release_service_kdbus (const char* sender_name,
  out:
   return retval;
 }
+#endif
 
 dbus_bool_t
 bus_registry_set_service_context_table (BusRegistry   *registry,
@@ -1476,13 +1500,29 @@ DBusConnection *
 bus_service_get_primary_owners_connection (BusService *service)
 {
   BusOwner *owner;
+#ifdef ENABLE_KDBUS_TRANSPORT
+  char unique_name[(unsigned int)(snprintf((char*)NULL, 0, "%llu", ULLONG_MAX) + sizeof(":1."))];
+#endif
 
   owner = bus_service_get_primary_owner (service);
 
+#ifdef ENABLE_KDBUS_TRANSPORT
+  if(!owner)
+    return NULL;
+  if(bus_context_is_kdbus(service->registry->context))
+  {
+    if(kdbus_get_name_owner(owner->conn, bus_service_get_name(service), unique_name) < 0)
+      return NULL;
+    return _bus_service_find_owner_connection(service, unique_name);  //bus_connections_find_conn_by_name would be safer? but slower
+  }
+  else
+    return owner->conn;
+#else
   if (owner != NULL)
     return owner->conn;
   else
     return NULL;
+#endif
 }
 
 BusOwner*
@@ -1511,6 +1551,22 @@ bus_service_get_allow_replacement (BusService *service)
   return owner->allow_replacement;
 }
 
+#ifdef ENABLE_KDBUS_TRANSPORT
+dbus_bool_t
+bus_service_get_is_kdbus_starter (BusService *service)
+{
+  BusOwner *owner;
+  DBusList *link;
+
+  _dbus_assert (service->owners != NULL);
+
+  link = _dbus_list_get_first_link (&service->owners);
+  owner = (BusOwner *) link->data;
+
+  return owner->is_kdbus_starter;
+}
+#endif
+
 dbus_bool_t
 bus_service_has_owner (BusService     *service,
                       DBusConnection *connection)
@@ -1545,8 +1601,11 @@ bus_service_list_queued_owners (BusService *service,
       owner = (BusOwner *) link->data;
       uname = bus_connection_get_name (owner->conn);
 
-      if (!_dbus_list_append (return_list, (char *)uname))
-        goto oom;
+#ifdef ENABLE_KDBUS_TRANSPORT
+      if(!owner->is_kdbus_starter)
+#endif
+          if (!_dbus_list_append (return_list, (char *)uname))
+              goto oom;
 
       link = _dbus_list_get_next_link (&service->owners, link);
     }