[lib-fix] moved dbus_connection_get_unix_user from daemon to library
[platform/upstream/dbus.git] / dbus / kdbus-common.c
index 2334ba7..837ed91 100644 (file)
 #include <dbus/dbus-internals.h>
 #include <dbus/dbus-shared.h>
 
-static struct kdbus_policy *make_policy_name(const char *name)
+static struct kdbus_item *make_policy_name(const char *name)
 {
-  struct kdbus_policy *p;
+  struct kdbus_item *p;
   __u64 size;
 
-  size = offsetof(struct kdbus_policy, name) + strlen(name) + 1;
+  size = offsetof(struct kdbus_item, policy.name) + strlen(name) + 1;
   p = malloc(size);
   if (!p)
-    return NULL;
+         return NULL;
   memset(p, 0, size);
   p->size = size;
-  p->type = KDBUS_POLICY_NAME;
-  strcpy(p->name, name);
+  p->type = KDBUS_ITEM_POLICY_NAME;
+  memcpy(p->policy.name, name, strlen(name) + 1);
 
   return p;
 }
 
-static struct kdbus_policy *make_policy_access(__u64 type, __u64 bits, __u64 id)
+static  struct kdbus_item *make_policy_access(__u64 type, __u64 bits, __u64 id)
 {
-  struct kdbus_policy *p;
+  struct kdbus_item *p;
   __u64 size = sizeof(*p);
 
   p = malloc(size);
   if (!p)
-    return NULL;
+         return NULL;
 
   memset(p, 0, size);
   p->size = size;
-  p->type = KDBUS_POLICY_ACCESS;
-  p->access.type = type;
-  p->access.bits = bits;
-  p->access.id = id;
+  p->type = KDBUS_ITEM_POLICY_ACCESS;
+  p->policy.access.type = type;
+  p->policy.access.bits = bits;
+  p->policy.access.id = id;
 
   return p;
 }
 
-static void append_policy(struct kdbus_cmd_policy *cmd_policy, struct kdbus_policy *policy, __u64 max_size)
+static void append_policy(struct kdbus_cmd_policy *cmd_policy, struct kdbus_item *policy, __u64 max_size)
 {
-  struct kdbus_policy *dst = (struct kdbus_policy *) ((char *) cmd_policy + cmd_policy->size);
+  struct kdbus_item *dst = (struct kdbus_item *) ((char *) cmd_policy + cmd_policy->size);
 
   if (cmd_policy->size + policy->size > max_size)
-    return;
+         return;
 
   memcpy(dst, policy, policy->size);
   cmd_policy->size += KDBUS_ALIGN8(policy->size);
@@ -101,7 +101,7 @@ static void append_policy(struct kdbus_cmd_policy *cmd_policy, struct kdbus_poli
 dbus_bool_t register_kdbus_policy(const char* name, DBusTransport *transport, unsigned long int owner_uid)
 {
   struct kdbus_cmd_policy *cmd_policy;
-  struct kdbus_policy *policy;
+  struct kdbus_item *policy;
   int size = 0xffff;
   int fd;
 
@@ -111,7 +111,7 @@ dbus_bool_t register_kdbus_policy(const char* name, DBusTransport *transport, un
   cmd_policy = alloca(size);
   memset(cmd_policy, 0, size);
 
-  policy = (struct kdbus_policy *) cmd_policy->policies;
+  policy = (struct kdbus_item *) cmd_policy->policies;
   cmd_policy->size = offsetof(struct kdbus_cmd_policy, policies);
 
   policy = make_policy_name(name);
@@ -169,12 +169,11 @@ int request_kdbus_name(int fd, const char *name, const __u64 flags, __u64 id)
     flags_kdbus |= KDBUS_NAME_QUEUE;
   if(flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
     flags_kdbus |= KDBUS_NAME_REPLACE_EXISTING;
-  if(flags & KDBUS_NAME_STARTER)
-    flags_kdbus |= KDBUS_NAME_STARTER;
+  if(flags & KDBUS_NAME_STARTER_NAME)
+    flags_kdbus |= KDBUS_NAME_STARTER_NAME;
 
   cmd_name->flags = flags_kdbus;
   cmd_name->id = id;
-  //   cmd_name->conn_flags = 0;
 
   _dbus_verbose("Request name - flags sent: 0x%llx       !!!!!!!!!\n", cmd_name->flags);
 
@@ -220,7 +219,7 @@ int release_kdbus_name(int fd, const char *name, __u64 id)
 
   if (ioctl(fd, KDBUS_CMD_NAME_RELEASE, cmd_name))
     {
-      if(errno == ESRCH)
+      if((errno == ESRCH) || (errno == ENXIO))
         return DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
       else if (errno == EPERM)
         return DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
@@ -232,3 +231,156 @@ int release_kdbus_name(int fd, const char *name, __u64 id)
 
   return DBUS_RELEASE_NAME_REPLY_RELEASED;
 }
+
+/**
+ * Performs kdbus query of id of the given name
+ *
+ * @param name name to query for
+ * @param transport transport
+ * @param pInfo nameInfo structure address to store info about the name
+ * @return 0 on success, -errno if failed
+ */
+int kdbus_NameQuery(const char* name, DBusTransport* transport, struct nameInfo* pInfo)
+{
+  struct kdbus_cmd_conn_info *cmd;
+  int ret;
+  int fd;
+  uint64_t size;
+  __u64 id = 0;
+
+  memset(pInfo, 0, sizeof(struct nameInfo));
+
+  if(!_dbus_transport_get_socket_fd(transport, &fd))
+    return -EPERM;
+
+  size = sizeof(struct kdbus_cmd_conn_info);
+  if((name[0] == ':') && (name[1] == '1') && (name[2] == '.'))  /* if name starts with ":1." it is a unique name and should be send as number */
+     id = strtoull(&name[3], NULL, 10);
+  if(id == 0)
+    size += strlen(name) + 1;
+
+  cmd = alloca(size);
+  if (!cmd)
+  {
+    _dbus_verbose("Error allocating memory for: %s,%s\n", _dbus_strerror (errno), _dbus_error_from_errno (errno));
+    return -errno;
+  }
+
+  memset(cmd, 0, sizeof(struct kdbus_cmd_conn_info));
+  cmd->size = size;
+  cmd->id = id;
+  if(id == 0)
+    memcpy(cmd->name, name, strlen(name) + 1);
+
+  again:
+  ret = ioctl(fd, KDBUS_CMD_CONN_INFO, cmd);
+  if (ret < 0)
+  {
+    if(errno == EINTR)
+      goto again;
+    pInfo->uniqueId = 0;
+    return -errno;
+  }
+  else
+  {
+    struct kdbus_conn_info *info;
+    struct kdbus_item *item;
+
+    info = (struct kdbus_conn_info *)((char*)dbus_transport_get_pool_pointer(transport) + cmd->offset);
+    pInfo->uniqueId = info->id;
+
+    item = info->items;
+    while((uint8_t *)(item) < (uint8_t *)(info) + info->size)
+    {
+      if(item->type == KDBUS_ITEM_CREDS)
+        {
+          pInfo->userId = item->creds.uid;
+          pInfo->processId = item->creds.pid;
+        }
+
+      if(item->type == KDBUS_ITEM_SECLABEL)
+        {
+          pInfo->sec_label_len = item->size - KDBUS_ITEM_HEADER_SIZE - 1;
+          if(pInfo->sec_label_len != 0)
+            {
+              pInfo->sec_label = malloc(pInfo->sec_label_len);
+              if(pInfo->sec_label == NULL)
+                ret = -1;
+              else
+                memcpy(pInfo->sec_label, item->data, pInfo->sec_label_len);
+            }
+        }
+
+      item = KDBUS_PART_NEXT(item);
+    }
+
+    again2:
+    if (ioctl(fd, KDBUS_CMD_FREE, &cmd->offset) < 0)
+    {
+      if(errno == EINTR)
+        goto again2;
+      _dbus_verbose("kdbus error freeing pool: %d (%m)\n", errno);
+      return -errno;
+    }
+  }
+
+  return ret;
+}
+
+/*
+ *  Asks kdbus for uid of the owner of the name given in the message
+ */
+dbus_bool_t kdbus_connection_get_unix_user(DBusConnection* connection, const char* name, unsigned long* uid, DBusError* error)
+{
+  struct nameInfo info;
+  int inter_ret;
+  dbus_bool_t ret = FALSE;
+
+  inter_ret = kdbus_NameQuery(name, dbus_connection_get_transport(connection), &info);
+  if(inter_ret == 0) //name found
+  {
+    _dbus_verbose("User id:%llu\n", (unsigned long long) info.userId);
+    *uid = info.userId;
+    return TRUE;
+  }
+  else if((inter_ret == -ENOENT) || (inter_ret == -ENXIO)) //name has no owner
+    {
+      _dbus_verbose ("Name %s has no owner.\n", name);
+      dbus_set_error (error, DBUS_ERROR_FAILED, "Could not get UID of name '%s': no such name", name);
+    }
+
+  else
+  {
+    _dbus_verbose("kdbus error determining UID: err %d (%m)\n", errno);
+    dbus_set_error (error, DBUS_ERROR_FAILED, "Could not determine UID for '%s'", name);
+  }
+
+  return ret;
+}
+
+/*
+ *  Asks kdbus for pid of the owner of the name given in the message
+ */
+dbus_bool_t kdbus_connection_get_unix_process_id(DBusConnection* connection, const char* name, unsigned long* pid, DBusError* error)
+{
+       struct nameInfo info;
+       int inter_ret;
+       dbus_bool_t ret = FALSE;
+
+       inter_ret = kdbus_NameQuery(name, dbus_connection_get_transport(connection), &info);
+       if(inter_ret == 0) //name found
+       {
+               _dbus_verbose("Process id:%llu\n", (unsigned long long) info.processId);
+               *pid = info.processId;
+               return TRUE;
+       }
+       else if((inter_ret == -ENOENT) || (inter_ret == -ENXIO)) //name has no owner
+               dbus_set_error (error, DBUS_ERROR_FAILED, "Could not get PID of name '%s': no such name", name);
+       else
+       {
+               _dbus_verbose("kdbus error determining PID: err %d (%m)\n", errno);
+               dbus_set_error (error, DBUS_ERROR_FAILED, "Could not determine PID for '%s'", name);
+       }
+
+       return ret;
+}