e2bfdb6aa1d67f1aa807c495310d22c9cf7e378f
[platform/upstream/dbus.git] / bus / kdbus-d.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* kdbus-d.c  kdbus related daemon functions
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
27 #include <dbus/dbus-connection-internal.h>
28 #include "kdbus-d.h"
29 #include <dbus/kdbus.h>
30 #include <dbus/dbus-bus.h>
31 #include "dispatch.h"
32 #include <dbus/kdbus-common.h>
33 #include <dbus/dbus-transport.h>
34 #include <dbus/dbus-transport-kdbus.h>
35 #include "connection.h"
36 #include "activation.h"
37 #include "services.h"
38
39 #include <utils.h>
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <fcntl.h>
43 #include <unistd.h>
44 #include <errno.h>
45
46 /*
47  * Converts string with unique name into __u64 id number. If the name is not unique, sets error.
48  */
49 __u64 sender_name_to_id(const char* name, DBusError* error)
50 {
51         __u64 sender_id = 0;
52
53         if(!strncmp(name, ":1.", 3)) /*if name is unique name it must be converted to unique id*/
54                 sender_id = strtoull(&name[3], NULL, 10);
55         else
56                 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Could not convert sender of the message into kdbus unique id");
57
58         return sender_id;
59 }
60
61 /**
62  * Seeks key in rule string, and duplicates value of the key into pValue.
63  * Because of the duplication, pValue must be freed after use.
64  *
65  * @param rule rule to look through
66  * @param key key to look for
67  * @param pValue pointer to value of the key found
68  * @return length of the value string, 0 means not found
69  */
70 static int parse_match_key(const char *rule, const char* key, char** pValue)
71 {
72   const char* pBegin;
73   const char* pValueEnd;
74   int value_length = 0;
75
76   pBegin = strstr(rule, key);
77   if(pBegin)
78   {
79     pBegin += strlen(key);
80     pValueEnd = strchr(pBegin, '\'');
81     if(pValueEnd)
82     {
83       value_length = pValueEnd - pBegin;
84       *pValue = strndup(pBegin, value_length);
85       if(*pValue)
86         _dbus_verbose ("found for key: %s value:'%s'\n", key, *pValue);
87     }
88   }
89   return value_length;
90 }
91
92 /**
93  * Adds a match rule to match broadcast messages going through the message bus.
94  * Do no affect messages addressed directly.
95  *
96  * The "rule" argument is the string form of a match rule.
97  *
98  * Only part of the dbus's matching capabilities is implemented in kdbus now, because of different mechanism.
99  * Current mapping:
100  * interface match key mapped to bloom
101  * sender match key mapped to src_name
102  *
103  * @param transport transport
104  * @param id id of connection for which the rule is to be added
105  * @param rule textual form of match rule
106   */
107 dbus_bool_t add_match_kdbus (DBusTransport* transport, __u64 id, const char *rule)
108 {
109   struct kdbus_cmd_match* pCmd_match;
110   struct kdbus_item *pItem;
111   __u64 src_id = KDBUS_MATCH_SRC_ID_ANY;
112   uint64_t size;
113   int name_size;
114   char* pName = NULL;
115   char* pInterface = NULL;
116   dbus_bool_t ret_value = FALSE;
117   int fd;
118   __u64 bloom_size;
119
120   if(!_dbus_transport_get_socket_fd(transport, &fd))
121     return FALSE;
122
123   bloom_size = dbus_transport_get_bloom_size(transport);
124
125   /*parsing rule and calculating size of command*/
126   size = sizeof(struct kdbus_cmd_match);
127   if(parse_match_key(rule, "interface='", &pInterface))       /*actual size is not important for interface because bloom size is defined by bus*/
128     size += KDBUS_PART_HEADER_SIZE + bloom_size;
129   name_size = parse_match_key(rule, "sender='", &pName);
130   if(name_size)
131   {
132     if(!strncmp(pName, ":1.", 3)) /*if name is unique name it must be converted to unique id*/
133     {
134       src_id = strtoull(&pName[3], NULL, 10);
135       free(pName);
136       pName = NULL;
137     }
138     else
139       size += KDBUS_ITEM_SIZE(name_size + 1);  //well known name
140   }
141
142   pCmd_match = alloca(size);
143   if(pCmd_match == NULL)
144     goto out;
145
146   pCmd_match->id = id;
147   pCmd_match->cookie = id;
148   pCmd_match->size = size;
149   pCmd_match->src_id = src_id;
150
151   pItem = pCmd_match->items;
152   if(pName)
153   {
154     pItem->type = KDBUS_MATCH_SRC_NAME;
155     pItem->size = KDBUS_PART_HEADER_SIZE + name_size + 1;
156     memcpy(pItem->str, pName, strlen(pName) + 1);
157     pItem = KDBUS_PART_NEXT(pItem);
158   }
159   if(pInterface)
160   {
161     pItem->type = KDBUS_MATCH_BLOOM;
162     pItem->size = KDBUS_PART_HEADER_SIZE + bloom_size;
163     strncpy(pItem->data, pInterface, bloom_size);
164   }
165
166   if(ioctl(fd, KDBUS_CMD_MATCH_ADD, pCmd_match))
167     _dbus_verbose("Failed adding match bus rule %s,\nerror: %d, %m\n", rule, errno);
168   else
169   {
170     _dbus_verbose("Added match bus rule %s for id:%llu\n", rule, (unsigned long long)id);
171     ret_value = TRUE;
172   }
173
174 out:
175   if(pName)
176     free(pName);
177   if(pInterface)
178     free(pInterface);
179   return ret_value;
180 }
181
182 /**
183  * Opposing to dbus, in kdbus removes all match rules with given
184  * cookie, which in this implementation is equal to uniqe id.
185  *
186  * @param transport transport
187  * @param id connection id for which rules are to be removed
188  */
189 dbus_bool_t remove_match_kdbus (DBusTransport* transport, __u64 id)
190 {
191   struct kdbus_cmd_match __attribute__ ((__aligned__(8))) cmd;
192   int fd;
193
194   if(!_dbus_transport_get_socket_fd(transport, &fd))
195     return FALSE;
196
197   cmd.cookie = id;
198   cmd.id = id;
199   cmd.size = sizeof(struct kdbus_cmd_match);
200
201   if(ioctl(fd, KDBUS_CMD_MATCH_REMOVE, &cmd))
202   {
203     _dbus_verbose("Failed removing match rule for id: %llu; error: %d, %m\n", (unsigned long long)id, errno);
204     return FALSE;
205   }
206   else
207   {
208     _dbus_verbose("Match rule removed correctly.\n");
209     return TRUE;
210   }
211 }
212
213 /**
214  * Performs kdbus query of id of the given name
215  *
216  * @param name name to query for
217  * @param transport transport
218  * @param pInfo nameInfo structure address to store info about the name
219  * @return 0 on success, -errno if failed
220  */
221 int kdbus_NameQuery(const char* name, DBusTransport* transport, struct nameInfo* pInfo)
222 {
223   struct kdbus_cmd_name_info *msg;
224   struct kdbus_item *item;
225   uint64_t size;
226   int ret;
227   uint64_t item_size;
228   int fd;
229
230   pInfo->sec_label_len = 0;
231   pInfo->sec_label = NULL;
232
233   if(!_dbus_transport_get_socket_fd(transport, &fd))
234     return -EPERM;
235
236   item_size = KDBUS_PART_HEADER_SIZE + strlen(name) + 1;
237   item_size = (item_size < 56) ? 56 : item_size;  //at least 56 bytes are needed by kernel to place info about name, otherwise error
238   size = sizeof(struct kdbus_cmd_name_info) + item_size;
239
240   msg = malloc(size);
241   if (!msg)
242   {
243     _dbus_verbose("Error allocating memory for: %s,%s\n", _dbus_strerror (errno), _dbus_error_from_errno (errno));
244     return -errno;
245   }
246
247   memset(msg, 0, size);
248   msg->size = size;
249     if((name[0] == ':') && (name[1] == '1') && (name[2] == '.'))  /* if name starts with ":1." it is a unique name and should be send as number */
250       msg->id = strtoull(&name[3], NULL, 10);
251     else
252       msg->id = 0;
253
254   item = msg->items;
255   item->type = KDBUS_NAME_INFO_ITEM_NAME;
256   item->size = item_size;
257   memcpy(item->str, name, strlen(name) + 1);
258
259   again:
260   ret = ioctl(fd, KDBUS_CMD_NAME_QUERY, msg);
261   if (ret < 0)
262   {
263     if(errno == EINTR)
264       goto again;
265     if(errno == EAGAIN)
266         goto again;
267     else if(ret == -ENOBUFS)
268     {
269       msg = realloc(msg, msg->size);  //prepare memory
270       if(msg != NULL)
271         goto again;
272     }
273     pInfo->uniqueId = 0;
274     ret = -errno;
275   }
276   else
277   {
278     pInfo->uniqueId = msg->id;
279     pInfo->userId = msg->creds.uid;
280     pInfo->processId = msg->creds.pid;
281     item = msg->items;
282     while((uint8_t *)(item) < (uint8_t *)(msg) + msg->size)
283     {
284       if(item->type == KDBUS_NAME_INFO_ITEM_SECLABEL)
285       {
286           pInfo->sec_label_len = item->size - KDBUS_PART_HEADER_SIZE - 1;
287         if(pInfo->sec_label_len != 0)
288         {
289           pInfo->sec_label = malloc(pInfo->sec_label_len);
290           if(pInfo->sec_label == NULL)
291             ret = -1;
292           else
293             memcpy(pInfo->sec_label, item->data, pInfo->sec_label_len);
294         }
295         break;
296       }
297       item = KDBUS_PART_NEXT(item);
298     }
299   }
300
301   free(msg);
302   return ret;
303 }
304
305 /*
306  * Creates kdbus bus of given type.
307  */
308 char* make_kdbus_bus(DBusBusType type, DBusError *error)
309 {
310     struct {
311         struct kdbus_cmd_bus_make head;
312         uint64_t n_size;
313         uint64_t n_type;
314         char name[64];
315     } __attribute__ ((__aligned__(8))) bus_make;
316
317     int fdc, ret;
318     char *bus;
319
320     _dbus_verbose("Opening /dev/kdbus/control\n");
321     fdc = open("/dev/kdbus/control", O_RDWR|O_CLOEXEC);
322     if (fdc < 0)
323     {
324         _dbus_verbose("--- error %d (%m)\n", fdc);
325         dbus_set_error(error, DBUS_ERROR_FAILED, "Opening /dev/kdbus/control failed: %d (%m)", fdc);
326         return NULL;
327     }
328
329     memset(&bus_make, 0, sizeof(bus_make));
330     bus_make.head.bloom_size = 64;
331     bus_make.head.flags = KDBUS_MAKE_ACCESS_WORLD;
332
333     if(type == DBUS_BUS_SYSTEM)
334         snprintf(bus_make.name, sizeof(bus_make.name), "%u-kdbus-%s", getuid(), "system");
335     else if(type == DBUS_BUS_SESSION)
336         snprintf(bus_make.name, sizeof(bus_make.name), "%u-kdbus", getuid());
337     else
338         snprintf(bus_make.name, sizeof(bus_make.name), "%u-kdbus-%u", getuid(), getpid());
339
340     bus_make.n_type = KDBUS_MAKE_NAME;
341     bus_make.n_size = KDBUS_PART_HEADER_SIZE + strlen(bus_make.name) + 1;
342     bus_make.head.size = sizeof(struct kdbus_cmd_bus_make) + bus_make.n_size;
343
344     _dbus_verbose("Creating bus '%s'\n", bus_make.name);
345     ret = ioctl(fdc, KDBUS_CMD_BUS_MAKE, &bus_make);
346     if (ret)
347     {
348         _dbus_verbose("--- error %d (%m)\n", ret);
349         dbus_set_error(error, DBUS_ERROR_FAILED, "Creating bus '%s' failed: %d (%m)", bus_make.name, fdc);
350         return NULL;
351     }
352
353     if (asprintf(&bus, "kdbus:path=/dev/kdbus/%s/bus", bus_make.name) < 0)
354     {
355         BUS_SET_OOM (error);
356         return NULL;
357     }
358
359     _dbus_verbose("Return value '%s'\n", bus);
360         return bus;
361 }
362
363 /*
364  * Minimal server init needed by context to go further.
365  */
366 DBusServer* empty_server_init(char* address)
367 {
368         return dbus_server_init_mini(address);
369 }
370
371 static dbus_bool_t add_matches_for_kdbus_broadcasts(DBusTransport* transport)
372 {
373   struct kdbus_cmd_match* pCmd_match;
374   struct kdbus_item *pItem;
375   uint64_t size;
376   int fd;
377
378   if(!_dbus_transport_get_socket_fd(transport, &fd))
379     {
380       errno = EPERM;
381       return FALSE;
382     }
383
384
385   size = sizeof(struct kdbus_cmd_match);
386   size += KDBUS_ITEM_SIZE(1)*3 + KDBUS_ITEM_SIZE(sizeof(__u64))*2;  /*3 name related items plus 2 id related items*/
387
388   pCmd_match = alloca(size);
389   if(pCmd_match == NULL)
390     {
391       errno = ENOMEM;
392       return FALSE;
393     }
394
395   pCmd_match->id = 1;
396   pCmd_match->cookie = 1;
397   pCmd_match->size = size;
398
399   pItem = pCmd_match->items;
400   pCmd_match->src_id = 0;
401   pItem->type = KDBUS_MATCH_NAME_CHANGE;
402   pItem->size = KDBUS_PART_HEADER_SIZE + 1;
403   pItem = KDBUS_PART_NEXT(pItem);
404   pItem->type = KDBUS_MATCH_NAME_ADD;
405   pItem->size = KDBUS_PART_HEADER_SIZE + 1;
406   pItem = KDBUS_PART_NEXT(pItem);
407   pItem->type = KDBUS_MATCH_NAME_REMOVE;
408   pItem->size = KDBUS_PART_HEADER_SIZE + 1;
409   pItem = KDBUS_PART_NEXT(pItem);
410   pItem->type = KDBUS_MATCH_ID_ADD;
411   pItem->size = KDBUS_PART_HEADER_SIZE + sizeof(__u64);
412   pItem = KDBUS_PART_NEXT(pItem);
413   pItem->type = KDBUS_MATCH_ID_REMOVE;
414   pItem->size = KDBUS_PART_HEADER_SIZE + sizeof(__u64);
415
416   if(ioctl(fd, KDBUS_CMD_MATCH_ADD, pCmd_match))
417     {
418       _dbus_verbose("Failed adding match rule for daemon, error: %d, %m\n", errno);
419       return FALSE;
420     }
421
422   _dbus_verbose("Added match rule for daemon correctly.\n");
423   return TRUE;
424 }
425
426 /*
427  * Connects daemon to bus created by him and adds matches for "system" broadcasts.
428  * Do not requests org.freedesktop.DBus name, because it's to early
429  * (some structures of BusContext are not ready yet).
430  */
431 DBusConnection* daemon_as_client(DBusBusType type, char* address, DBusError *error)
432 {
433   DBusConnection* connection;
434
435   dbus_bus_set_bus_connection_address(type, address);
436
437   connection = dbus_bus_get_private(type, error);  /*todo possibly could be optimised by using lower functions*/
438   if(connection == NULL)
439     return NULL;
440
441   if(!add_matches_for_kdbus_broadcasts(dbus_connection_get_transport(connection)))
442     {
443       dbus_set_error (error, _dbus_error_from_errno (errno), "Could not add match for daemon, %s", _dbus_strerror_from_errno ());
444       goto failed;
445     }
446
447   if(dbus_error_is_set(error))
448     {
449       failed:
450       _dbus_connection_close_possibly_shared (connection);
451       dbus_connection_unref (connection);
452       connection = NULL;
453     }
454   else
455     _dbus_verbose ("Daemon connected as kdbus client.\n");
456
457   return connection;
458 }
459
460 /*
461  * Asks bus for org.freedesktop.DBus well-known name.
462  */
463 dbus_bool_t register_daemon_name(DBusConnection* connection)
464 {
465     DBusString daemon_name;
466     dbus_bool_t retval = FALSE;
467     BusTransaction *transaction;
468
469     _dbus_string_init_const(&daemon_name, DBUS_SERVICE_DBUS);
470     if(!register_kdbus_policy(DBUS_SERVICE_DBUS, dbus_connection_get_transport(connection), geteuid()))
471       return FALSE;
472
473     if(kdbus_request_name(connection, &daemon_name, 0, 0) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
474        return FALSE;
475
476     transaction = bus_transaction_new (bus_connection_get_context(connection));
477     if (transaction == NULL)
478     {
479         kdbus_release_name(connection, &daemon_name, 0);
480         goto out;
481     }
482
483     if(!bus_registry_ensure (bus_connection_get_registry (connection), &daemon_name, connection, 0, transaction, NULL))
484     {
485         kdbus_release_name(connection, &daemon_name, 0);
486         goto out;
487     }
488
489     retval = TRUE;
490
491 out:
492         bus_transaction_cancel_and_free(transaction);
493     return retval;
494 }
495
496 dbus_uint32_t kdbus_request_name(DBusConnection* connection, const DBusString *service_name, dbus_uint32_t flags, __u64 sender_id)
497 {
498         int fd;
499
500         _dbus_transport_get_socket_fd(dbus_connection_get_transport(connection), &fd);
501
502         return request_kdbus_name(fd, _dbus_string_get_const_data(service_name), flags, sender_id);
503 }
504
505 dbus_uint32_t kdbus_release_name(DBusConnection* connection, const DBusString *service_name, __u64 sender_id)
506 {
507         int fd;
508
509         _dbus_transport_get_socket_fd(dbus_connection_get_transport(connection), &fd);
510
511         return release_kdbus_name(fd, _dbus_string_get_const_data(service_name), sender_id);
512 }
513
514 /*
515  * Asks kdbus for well-known names registered on the bus
516  */
517 dbus_bool_t kdbus_list_services (DBusConnection* connection, char ***listp, int *array_len)
518 {
519         int fd;
520         struct kdbus_cmd_names* pCmd;
521         __u64 cmd_size;
522         dbus_bool_t ret_val = FALSE;
523         char** list;
524         int list_len = 0;
525         int i = 0;
526         int j;
527
528         cmd_size = sizeof(struct kdbus_cmd_names) + KDBUS_ITEM_SIZE(1);
529         pCmd = malloc(cmd_size);
530         if(pCmd == NULL)
531                 goto out;
532         pCmd->size = cmd_size;
533
534         _dbus_transport_get_socket_fd(dbus_connection_get_transport(connection), &fd);
535
536 again:
537         cmd_size = 0;
538         if(ioctl(fd, KDBUS_CMD_NAME_LIST, pCmd))
539         {
540                 if(errno == EINTR)
541                         goto again;
542                 if(errno == ENOBUFS)                    //buffer to small to put all names into it
543                         cmd_size = pCmd->size;          //here kernel tells how much memory it needs
544                 else
545                 {
546                         _dbus_verbose("kdbus error asking for name list: err %d (%m)\n",errno);
547                         goto out;
548                 }
549         }
550         if(cmd_size)  //kernel needs more memory
551         {
552                 pCmd = realloc(pCmd, cmd_size);  //prepare memory
553                 if(pCmd == NULL)
554                         return FALSE;
555                 goto again;                                             //and try again
556         }
557         else
558         {
559                 struct kdbus_cmd_name* pCmd_name;
560
561                 for (pCmd_name = pCmd->names; (uint8_t *)(pCmd_name) < (uint8_t *)(pCmd) + pCmd->size; pCmd_name = KDBUS_PART_NEXT(pCmd_name))
562                         list_len++;
563
564                 list = malloc(sizeof(char*) * (list_len + 1));
565                 if(list == NULL)
566                         goto out;
567
568                 for (pCmd_name = pCmd->names; (uint8_t *)(pCmd_name) < (uint8_t *)(pCmd) + pCmd->size; pCmd_name = KDBUS_PART_NEXT(pCmd_name))
569                 {
570                         list[i] = strdup(pCmd_name->name);
571                         if(list[i] == NULL)
572                         {
573                                 for(j=0; j<i; j++)
574                                         free(list[j]);
575                                 free(list);
576                                 goto out;
577                         }
578                         _dbus_verbose ("Name %d: %s\n", i, list[i]);
579                         ++i;
580                 }
581                 list[i] = NULL;
582         }
583
584         *array_len = list_len;
585         *listp = list;
586         ret_val = TRUE;
587
588 out:
589         if(pCmd)
590                 free(pCmd);
591         return ret_val;
592 }
593
594 /*
595  *  Register match rule in kdbus on behalf of sender of the message
596  */
597 dbus_bool_t kdbus_add_match_rule (DBusConnection* connection, DBusMessage* message, const char* text, DBusError* error)
598 {
599         __u64 sender_id;
600
601         sender_id = sender_name_to_id(dbus_message_get_sender(message), error);
602         if(dbus_error_is_set(error))
603                 return FALSE;
604
605         if(!add_match_kdbus (dbus_connection_get_transport(connection), sender_id, text))
606         {
607               dbus_set_error (error, _dbus_error_from_errno (errno), "Could not add match for id:%d, %s",
608                               sender_id, _dbus_strerror_from_errno ());
609               return FALSE;
610         }
611
612         return TRUE;
613 }
614
615 /*
616  *  Removes match rule in kdbus on behalf of sender of the message
617  */
618 dbus_bool_t kdbus_remove_match (DBusConnection* connection, DBusMessage* message, DBusError* error)
619 {
620         __u64 sender_id;
621
622         sender_id = sender_name_to_id(dbus_message_get_sender(message), error);
623         if(dbus_error_is_set(error))
624                 return FALSE;
625
626         if(!remove_match_kdbus (dbus_connection_get_transport(connection), sender_id))
627         {
628               dbus_set_error (error, _dbus_error_from_errno (errno), "Could not remove match rules for id:%d", sender_id);
629               return FALSE;
630         }
631
632         return TRUE;
633 }
634
635 int kdbus_get_name_owner(DBusConnection* connection, const char* name, char* owner)
636 {
637   int ret;
638   struct nameInfo info;
639
640   ret = kdbus_NameQuery(name, dbus_connection_get_transport(connection), &info);
641   if(ret == 0) //unique id of the name
642   {
643     sprintf(owner, ":1.%llu", (unsigned long long int)info.uniqueId);
644     _dbus_verbose("Unique name discovered:%s\n", owner);
645   }
646   else if(ret != -ENOENT)
647     _dbus_verbose("kdbus error sending name query: err %d (%m)\n", errno);
648
649   return ret;
650 }
651
652 /*
653  *  Asks kdbus for uid of the owner of the name given in the message
654  */
655 dbus_bool_t kdbus_get_unix_user(DBusConnection* connection, const char* name, unsigned long* uid, DBusError* error)
656 {
657   struct nameInfo info;
658   int inter_ret;
659   dbus_bool_t ret = FALSE;
660
661   inter_ret = kdbus_NameQuery(name, dbus_connection_get_transport(connection), &info);
662   if(inter_ret == 0) //name found
663   {
664     _dbus_verbose("User id:%llu\n", (unsigned long long) info.userId);
665     *uid = info.userId;
666     return TRUE;
667   }
668   else if(inter_ret == -ENOENT)  //name has no owner
669     {
670       _dbus_verbose ("Name %s has no owner.\n", name);
671       dbus_set_error (error, DBUS_ERROR_FAILED, "Could not get UID of name '%s': no such name", name);
672     }
673
674   else
675   {
676     _dbus_verbose("kdbus error determining UID: err %d (%m)\n", errno);
677     dbus_set_error (error, DBUS_ERROR_FAILED, "Could not determine UID for '%s'", name);
678   }
679
680   return ret;
681 }
682
683 /*
684  *  Asks kdbus for pid of the owner of the name given in the message
685  */
686 dbus_bool_t kdbus_get_connection_unix_process_id(DBusConnection* connection, const char* name, unsigned long* pid, DBusError* error)
687 {
688         struct nameInfo info;
689         int inter_ret;
690         dbus_bool_t ret = FALSE;
691
692         inter_ret = kdbus_NameQuery(name, dbus_connection_get_transport(connection), &info);
693         if(inter_ret == 0) //name found
694         {
695                 _dbus_verbose("Process id:%llu\n", (unsigned long long) info.processId);
696                 *pid = info.processId;
697                 return TRUE;
698         }
699         else if(inter_ret == -ENOENT)  //name has no owner
700                 dbus_set_error (error, DBUS_ERROR_FAILED, "Could not get PID of name '%s': no such name", name);
701         else
702         {
703                 _dbus_verbose("kdbus error determining PID: err %d (%m)\n", errno);
704                 dbus_set_error (error, DBUS_ERROR_FAILED, "Could not determine PID for '%s'", name);
705         }
706
707         return ret;
708 }
709
710 /*
711  *  Asks kdbus for selinux_security_context of the owner of the name given in the message
712  */
713 dbus_bool_t kdbus_get_connection_unix_selinux_security_context(DBusConnection* connection, DBusMessage* message, DBusMessage* reply, DBusError* error)
714 {
715         char* name = NULL;
716         struct nameInfo info;
717         int inter_ret;
718         dbus_bool_t ret = FALSE;
719
720         dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID);
721         inter_ret = kdbus_NameQuery(name, dbus_connection_get_transport(connection), &info);
722         if(inter_ret == -ENOENT)  //name has no owner
723                 dbus_set_error (error, DBUS_ERROR_FAILED, "Could not get security context of name '%s': no such name", name);
724         else if(inter_ret < 0)
725         {
726                 _dbus_verbose("kdbus error determining security context: err %d (%m)\n", errno);
727                 dbus_set_error (error, DBUS_ERROR_FAILED, "Could not determine security context for '%s'", name);
728         }
729         else
730         {
731                 if (!dbus_message_append_args (reply, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &info.sec_label, info.sec_label_len, DBUS_TYPE_INVALID))
732                 {
733                       _DBUS_SET_OOM (error);
734                       return FALSE;
735                 }
736                 ret = TRUE;
737         }
738
739         return ret;
740 }
741
742 /**
743  * Gets the UNIX user ID of the connection from kdbus, if known. Returns #TRUE if
744  * the uid is filled in.  Always returns #FALSE on non-UNIX platforms
745  * for now., though in theory someone could hook Windows to NIS or
746  * something.  Always returns #FALSE prior to authenticating the
747  * connection.
748  *
749  * The UID of is only read by bus daemon from kdbus. You can not
750  * call this function from client side of the connection.
751  *
752  * You can ask the bus to tell you the UID of another connection though
753  * if you like; this is done with dbus_bus_get_unix_user().
754  *
755  * @param connection the connection
756  * @param uid return location for the user ID
757  * @returns #TRUE if uid is filled in with a valid user ID
758  */
759 dbus_bool_t
760 dbus_connection_get_unix_user (DBusConnection *connection,
761                                unsigned long  *uid)
762 {
763   _dbus_return_val_if_fail (connection != NULL, FALSE);
764   _dbus_return_val_if_fail (uid != NULL, FALSE);
765
766   return kdbus_get_unix_user(connection, bus_connection_get_name(connection), uid, NULL);
767 }
768
769 /**
770  * Gets the process ID of the connection if any.
771  * Returns #TRUE if the pid is filled in.
772  *
773  * @param connection the connection
774  * @param pid return location for the process ID
775  * @returns #TRUE if uid is filled in with a valid process ID
776  */
777 dbus_bool_t
778 dbus_connection_get_unix_process_id (DBusConnection *connection,
779              unsigned long  *pid)
780 {
781   _dbus_return_val_if_fail (connection != NULL, FALSE);
782   _dbus_return_val_if_fail (pid != NULL, FALSE);
783
784   return kdbus_get_connection_unix_process_id(connection, bus_connection_get_name(connection), pid, NULL);
785 }
786
787 /*
788  * Create connection structure for given name. It is needed to control starters - activatable services
789  * and for ListQueued method (as long as kdbus is not supporting it). This connections don't have it's own
790  * fd so it is set up on the basis of daemon's transport. Functionality of such connection is limited.
791  */
792 DBusConnection* create_phantom_connection(DBusConnection* connection, const char* name, DBusError* error)
793 {
794     DBusConnection *phantom_connection;
795     DBusString Sname;
796
797     _dbus_string_init_const(&Sname, name);
798
799     phantom_connection = _dbus_connection_new_for_used_transport (dbus_connection_get_transport(connection));
800     if(phantom_connection == NULL)
801         return FALSE;
802     if(!bus_connections_setup_connection(bus_connection_get_connections(connection), phantom_connection))
803     {
804         dbus_connection_unref_phantom(phantom_connection);
805         phantom_connection = NULL;
806         dbus_set_error (error, DBUS_ERROR_FAILED , "Name \"%s\" could not be acquired", name);
807         goto out;
808     }
809     if(!bus_connection_complete(phantom_connection, &Sname, error))
810     {
811         bus_connection_disconnected(phantom_connection);
812         phantom_connection = NULL;
813         goto out;
814     }
815
816     _dbus_verbose ("Created phantom connection for %s\n", bus_connection_get_name(phantom_connection));
817
818 out:
819     return phantom_connection;
820 }
821
822 /*
823  * Registers activatable services as kdbus starters.
824  */
825 dbus_bool_t register_kdbus_starters(DBusConnection* connection)
826 {
827     int i,j, len;
828     char **services;
829     dbus_bool_t retval = FALSE;
830     int fd;
831     BusTransaction *transaction;
832     DBusString name;
833     DBusTransport* transport;
834     unsigned long int euid;
835
836     transaction = bus_transaction_new (bus_connection_get_context(connection));
837     if (transaction == NULL)
838         return FALSE;
839
840     if (!bus_activation_list_services (bus_connection_get_activation (connection), &services, &len))
841         return FALSE;
842
843     transport = dbus_connection_get_transport(connection);
844     euid = geteuid();
845
846     if(!_dbus_transport_get_socket_fd (transport, &fd))
847       return FALSE;
848
849     _dbus_string_init(&name);
850
851     for(i=0; i<len; i++)
852     {
853         if(!register_kdbus_policy(services[i], transport, euid))
854           goto out;
855
856         if (request_kdbus_name(fd, services[i], (DBUS_NAME_FLAG_ALLOW_REPLACEMENT | KDBUS_NAME_STARTER) , 0) < 0)
857             goto out;
858
859         if(!_dbus_string_append(&name, services[i]))
860                 goto out;
861         if(!bus_registry_ensure (bus_connection_get_registry (connection), &name, connection,
862                         (DBUS_NAME_FLAG_ALLOW_REPLACEMENT | KDBUS_NAME_STARTER), transaction, NULL))
863                 goto out;
864         if(!_dbus_string_set_length(&name, 0))
865                 goto out;
866     }
867     retval = TRUE;
868
869 out:
870     if(retval == FALSE)
871     {
872         for(j=0; j<i; j++)
873             release_kdbus_name(fd, services[j], 0);
874     }
875     dbus_free_string_array (services);
876     _dbus_string_free(&name);
877     bus_transaction_cancel_and_free(transaction);
878     return retval;
879 }
880
881 /*
882  * Updates kdbus starters (activatable services) after configuration was reloaded.
883  * It releases all previous starters and registers all new.
884  */
885 dbus_bool_t update_kdbus_starters(DBusConnection* connection)
886 {
887     dbus_bool_t retval = FALSE;
888     DBusList **services_old;
889     DBusList *link;
890     BusService *service = NULL;
891     BusTransaction *transaction;
892     int fd;
893
894     transaction = bus_transaction_new (bus_connection_get_context(connection));
895     if (transaction == NULL)
896         return FALSE;
897
898     if(!_dbus_transport_get_socket_fd(dbus_connection_get_transport(connection), &fd))
899         goto out;
900
901     services_old = bus_connection_get_services_owned(connection);
902     link = _dbus_list_get_first_link(services_old);
903     link = _dbus_list_get_next_link (services_old, link); //skip org.freedesktop.DBus which is not starter
904
905     while (link != NULL)
906     {
907         int ret;
908
909         service = (BusService*) link->data;
910         if(service == NULL)
911             goto out;
912
913         ret = release_kdbus_name(fd, bus_service_get_name(service), 0);
914
915         if (ret == DBUS_RELEASE_NAME_REPLY_RELEASED)
916         {
917             if(!bus_service_remove_owner(service, connection, transaction, NULL))
918                 _dbus_verbose ("Unable to remove\n");
919         }
920         else if(ret < 0)
921             goto out;
922
923         link = _dbus_list_get_next_link (services_old, link);
924     }
925
926     if(!register_kdbus_starters(connection))
927     {
928         _dbus_verbose ("Registering kdbus starters for dbus activatable names failed!\n");
929         goto out;
930     }
931     retval = TRUE;
932
933 out:
934         bus_transaction_cancel_and_free(transaction);
935     return retval;
936 }
937
938 /*
939  * Analyzes system broadcasts about id and name changes.
940  * Basing on this it sends NameAcquired and NameLost signals and clear phantom connections.
941  */
942 void handleNameOwnerChanged(DBusMessage *msg, BusTransaction *transaction, DBusConnection *connection)
943 {
944     const char *name, *old, *new;
945
946     if(!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID))
947     {
948         _dbus_verbose ("Couldn't get args of NameOwnerChanged signal.\n");//, error.message);
949         return;
950     }
951
952     _dbus_verbose ("Got NameOwnerChanged signal:\nName: %s\nOld: %s\nNew: %s\n", name, old, new);
953
954     if(!strncmp(name, ":1.", 3))/*if it starts from :1. it is unique name - this might be IdRemoved info*/
955     {
956         if(!strcmp(name, old))  //yes it is - someone has disconnected
957         {
958             DBusConnection* conn;
959
960             conn = bus_connections_find_conn_by_name(bus_connection_get_connections(connection), name);
961             if(conn)
962                 bus_connection_disconnected(conn);
963         }
964     }
965     else //it is well-known name
966     {
967         if((*old != 0) && (strcmp(old, ":1.1")))
968         {
969             DBusMessage *message;
970
971             if(bus_connections_find_conn_by_name(bus_connection_get_connections(connection), old) == NULL)
972                 goto next;
973
974             _dbus_verbose ("Owner '%s' lost name '%s'. Sending NameLost.\n", old, name);
975
976             message = dbus_message_new_signal (DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "NameLost");
977             if (message == NULL)
978                 goto next;
979
980             if (!dbus_message_set_destination (message, old) || !dbus_message_append_args (message,
981                                                                  DBUS_TYPE_STRING, &name,
982                                                                  DBUS_TYPE_INVALID))
983             {
984                 dbus_message_unref (message);
985                 goto next;
986             }
987
988             bus_transaction_send_from_driver (transaction, connection, message);
989             dbus_message_unref (message);
990         }
991     next:
992         if((*new != 0) && (strcmp(new, ":1.1")))
993         {
994             DBusMessage *message;
995
996             _dbus_verbose ("Owner '%s' acquired name '%s'. Sending NameAcquired.\n", new, name);
997
998             message = dbus_message_new_signal (DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "NameAcquired");
999             if (message == NULL)
1000                 return;
1001
1002             if (!dbus_message_set_destination (message, new) || !dbus_message_append_args (message,
1003                                                                  DBUS_TYPE_STRING, &name,
1004                                                                  DBUS_TYPE_INVALID))
1005             {
1006                 dbus_message_unref (message);
1007                 return;
1008             }
1009
1010             bus_transaction_send_from_driver (transaction, connection, message);
1011             dbus_message_unref (message);
1012         }
1013     }
1014
1015     if(bus_transaction_send(transaction, connection, msg))
1016       _dbus_verbose ("NameOwnerChanged sent\n");
1017     else
1018       _dbus_verbose ("Sending NameOwnerChanged failed\n");
1019 }