e0e6305295ac65ce61c31c18480594111bc39f5f
[platform/upstream/dbus.git] / dbus / kdbus-common.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* kdbus-common.c  kdbus related utils for daemon and libdbus
3  *
4  * Copyright (C) 2013  Samsung Electronics
5  *
6  * Licensed under the Academic Free License version 2.1
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version and under the terms of the GNU
12  * Lesser General Public License as published by the
13  * Free Software Foundation; either version 2.1 of the License, or (at
14  * your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
24  *
25  */
26 #include "kdbus.h"
27 #include "kdbus-common.h"
28 #include "dbus-transport-kdbus.h"
29 #include <string.h>
30 #include <stddef.h>
31 #include <stdlib.h>
32 #include <errno.h>
33 #include <unistd.h>
34 #include <dbus/dbus-internals.h>
35 #include <dbus/dbus-shared.h>
36
37 static struct kdbus_item *make_policy_name(const char *name)
38 {
39   struct kdbus_item *p;
40   __u64 size;
41
42   size = offsetof(struct kdbus_item, policy.name) + strlen(name) + 1;
43   p = malloc(size);
44   if (!p)
45           return NULL;
46   memset(p, 0, size);
47   p->size = size;
48   p->type = KDBUS_ITEM_POLICY_NAME;
49   memcpy(p->policy.name, name, strlen(name) + 1);
50
51   return p;
52 }
53
54 static  struct kdbus_item *make_policy_access(__u64 type, __u64 bits, __u64 id)
55 {
56   struct kdbus_item *p;
57   __u64 size = sizeof(*p);
58
59   p = malloc(size);
60   if (!p)
61           return NULL;
62
63   memset(p, 0, size);
64   p->size = size;
65   p->type = KDBUS_ITEM_POLICY_ACCESS;
66   p->policy.access.type = type;
67   p->policy.access.bits = bits;
68   p->policy.access.id = id;
69
70   return p;
71 }
72
73 static void append_policy(struct kdbus_cmd_policy *cmd_policy, struct kdbus_item *policy, __u64 max_size)
74 {
75   struct kdbus_item *dst = (struct kdbus_item *) ((char *) cmd_policy + cmd_policy->size);
76
77   if (cmd_policy->size + policy->size > max_size)
78           return;
79
80   memcpy(dst, policy, policy->size);
81   cmd_policy->size += KDBUS_ALIGN8(policy->size);
82   free(policy);
83 }
84
85 /**
86  * Registers kdbus policy for given connection.
87  *
88  * Policy sets rights of the name (unique or well known) on the bus. Without policy it is
89  * not possible to send or receive messages. It must be set separately for unique id and
90  * well known name of the connection. It is set after registering on the bus, but before
91  * requesting for name. The policy is valid for the given name, not for the connection.
92  *
93  * Name of the policy equals name on the bus.
94  *
95  * @param name name of the policy = name of the connection
96  * @param transport - transport
97  * @param owner_uid - uid or euid of the process being owner of the name
98  *
99  * @returns #TRUE on success
100  */
101 dbus_bool_t register_kdbus_policy(const char* name, DBusTransport *transport, unsigned long int owner_uid)
102 {
103   struct kdbus_cmd_policy *cmd_policy;
104   struct kdbus_item *policy;
105   int size = 0xffff;
106   int fd;
107
108   if(!_dbus_transport_get_socket_fd (transport, &fd))
109     return FALSE;
110
111   cmd_policy = alloca(size);
112   memset(cmd_policy, 0, size);
113
114   policy = (struct kdbus_item *) cmd_policy->policies;
115   cmd_policy->size = offsetof(struct kdbus_cmd_policy, policies);
116
117   policy = make_policy_name(name);
118   append_policy(cmd_policy, policy, size);
119
120   policy = make_policy_access(KDBUS_POLICY_ACCESS_USER, KDBUS_POLICY_OWN, owner_uid);
121   append_policy(cmd_policy, policy, size);
122
123   policy = make_policy_access(KDBUS_POLICY_ACCESS_WORLD, KDBUS_POLICY_RECV, 0);
124   append_policy(cmd_policy, policy, size);
125
126   policy = make_policy_access(KDBUS_POLICY_ACCESS_WORLD, KDBUS_POLICY_SEND, 0);
127   append_policy(cmd_policy, policy, size);
128
129   if (ioctl(fd, KDBUS_CMD_EP_POLICY_SET, cmd_policy) < 0)
130     {
131       _dbus_verbose ("Error setting policy: %m, %d\n", errno);
132       return FALSE;
133     }
134
135   _dbus_verbose("Policy %s set correctly\n", name);
136   return TRUE;
137 }
138
139 /**
140  *
141  * Asks the bus to assign the given name to the connection.
142  *
143  * Use same flags as original dbus version with one exception below.
144  * Result flag #DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER is currently
145  * never returned by kdbus, instead DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
146  * is returned by kdbus.
147  *
148  * @param fd - file descriptor of the connection
149  * @param name the name to request
150  * @param flags flags
151  * @param id unique id of the connection for which the name is being registered
152  * @returns a DBus result code on success, -errno on error
153  */
154 int request_kdbus_name(int fd, const char *name, const __u64 flags, __u64 id)
155 {
156   struct kdbus_cmd_name *cmd_name;
157
158   __u64 size = sizeof(*cmd_name) + strlen(name) + 1;
159   __u64 flags_kdbus = 0;
160
161   cmd_name = alloca(size);
162
163   strcpy(cmd_name->name, name);
164   cmd_name->size = size;
165
166   if(flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT)
167     flags_kdbus |= KDBUS_NAME_ALLOW_REPLACEMENT;
168   if(!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE))
169     flags_kdbus |= KDBUS_NAME_QUEUE;
170   if(flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
171     flags_kdbus |= KDBUS_NAME_REPLACE_EXISTING;
172   if(flags & KDBUS_NAME_STARTER_NAME)
173     flags_kdbus |= KDBUS_NAME_STARTER_NAME;
174
175   cmd_name->flags = flags_kdbus;
176   cmd_name->id = id;
177
178   _dbus_verbose("Request name - flags sent: 0x%llx       !!!!!!!!!\n", cmd_name->flags);
179
180   if (ioctl(fd, KDBUS_CMD_NAME_ACQUIRE, cmd_name))
181     {
182       _dbus_verbose ("error acquiring name '%s': %m, %d\n", name, errno);
183       if(errno == EEXIST)
184         return DBUS_REQUEST_NAME_REPLY_EXISTS;
185       if(errno == EALREADY)
186         return DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
187       return -errno;
188     }
189
190   _dbus_verbose("Request name - received flag: 0x%llx       !!!!!!!!!\n", cmd_name->flags);
191
192   if(cmd_name->flags & KDBUS_NAME_IN_QUEUE)
193     return DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
194   else
195     return DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
196 }
197
198 /**
199  *
200  * Releases well-known name - the connections resign from the name
201  * which can be then assigned to another connection or the connection
202  * is being removed from the queue for that name
203  *
204  * @param fd - file descriptor of the connection
205  * @param name the name to request
206  * @param id unique id of the connection for which the name is being released
207  * @returns a DBus result code on success, -errno on error
208  */
209 int release_kdbus_name(int fd, const char *name, __u64 id)
210 {
211   struct kdbus_cmd_name *cmd_name;
212
213   __u64 size = sizeof(*cmd_name) + strlen(name) + 1;
214
215   cmd_name = alloca(size);
216   cmd_name->id = id;
217   strcpy(cmd_name->name, name);
218   cmd_name->size = size;
219
220   if (ioctl(fd, KDBUS_CMD_NAME_RELEASE, cmd_name))
221     {
222       if((errno == ESRCH) || (errno == ENXIO))
223         return DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
224       else if (errno == EPERM)
225         return DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
226       _dbus_verbose ("error releasing name '%s' for id:%llu. Error: %m, %d\n", name, (unsigned long long)id, errno);
227       return -errno;
228     }
229
230   _dbus_verbose("Name '%s' released\n", name);
231
232   return DBUS_RELEASE_NAME_REPLY_RELEASED;
233 }