[daemon-fix][daemon-dev] Fixed crashing when name is primary owned again
[platform/upstream/dbus.git] / bus / services.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* services.c  Service management
3  *
4  * Copyright (C) 2003  Red Hat, Inc.
5  * Copyright (C) 2003  CodeFactory AB
6  *
7  * Licensed under the Academic Free License version 2.1
8  * 
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24
25 #include <config.h>
26 #include <dbus/dbus-hash.h>
27 #include <dbus/dbus-list.h>
28 #include <dbus/dbus-mempool.h>
29 #include <dbus/dbus-marshal-validate.h>
30 #include <linux/types.h>
31 #include <errno.h>
32 #include <stdlib.h>
33
34
35 #include "driver.h"
36 #include "services.h"
37 #include "connection.h"
38 #include "utils.h"
39 #include "activation.h"
40 #include "policy.h"
41 #include "bus.h"
42 #include "selinux.h"
43 #include "kdbus-d.h"
44
45 struct BusService
46 {
47   int refcount;
48
49   BusRegistry *registry;
50   char *name;
51   DBusList *owners;
52 };
53
54 struct BusOwner
55 {
56   int refcount;
57
58   BusService *service;
59   DBusConnection *conn;
60
61   unsigned int allow_replacement : 1;
62   unsigned int do_not_queue : 1;
63 };
64
65 struct BusRegistry
66 {
67   int refcount;
68
69   BusContext *context;
70   
71   DBusHashTable *service_hash;
72   DBusMemPool   *service_pool;
73   DBusMemPool   *owner_pool;
74
75   DBusHashTable *service_sid_table;
76 };
77
78 BusRegistry*
79 bus_registry_new (BusContext *context)
80 {
81   BusRegistry *registry;
82
83   registry = dbus_new0 (BusRegistry, 1);
84   if (registry == NULL)
85     return NULL;
86
87   registry->refcount = 1;
88   registry->context = context;
89   
90   registry->service_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
91                                                  NULL, NULL);
92   if (registry->service_hash == NULL)
93     goto failed;
94   
95   registry->service_pool = _dbus_mem_pool_new (sizeof (BusService),
96                                                TRUE);
97
98   if (registry->service_pool == NULL)
99     goto failed;
100
101   registry->owner_pool = _dbus_mem_pool_new (sizeof (BusOwner),
102                                              TRUE);
103
104   if (registry->owner_pool == NULL)
105     goto failed;
106
107   registry->service_sid_table = NULL;
108   
109   return registry;
110
111  failed:
112   bus_registry_unref (registry);
113   return NULL;
114 }
115
116 BusRegistry *
117 bus_registry_ref (BusRegistry *registry)
118 {
119   _dbus_assert (registry->refcount > 0);
120   registry->refcount += 1;
121
122   return registry;
123 }
124
125 void
126 bus_registry_unref  (BusRegistry *registry)
127 {
128   _dbus_assert (registry->refcount > 0);
129   registry->refcount -= 1;
130
131   if (registry->refcount == 0)
132     {
133       if (registry->service_hash)
134         _dbus_hash_table_unref (registry->service_hash);
135       if (registry->service_pool)
136         _dbus_mem_pool_free (registry->service_pool);
137       if (registry->owner_pool)
138         _dbus_mem_pool_free (registry->owner_pool);
139       if (registry->service_sid_table)
140         _dbus_hash_table_unref (registry->service_sid_table);
141       
142       dbus_free (registry);
143     }
144 }
145
146 BusService*
147 bus_registry_lookup (BusRegistry      *registry,
148                      const DBusString *service_name)
149 {
150   BusService *service;
151
152   service = _dbus_hash_table_lookup_string (registry->service_hash,
153                                             _dbus_string_get_const_data (service_name));
154
155   return service;
156 }
157
158 static DBusList *
159 _bus_service_find_owner_link (BusService *service,
160                               DBusConnection *connection)
161 {
162   DBusList *link;
163   
164   link = _dbus_list_get_first_link (&service->owners);
165
166   while (link != NULL)
167     {
168       BusOwner *bus_owner;
169
170       bus_owner = (BusOwner *) link->data;
171       if (bus_owner->conn == connection) 
172         break;
173
174       link = _dbus_list_get_next_link (&service->owners, link);
175     }
176
177   return link;
178 }
179
180 static void
181 bus_owner_set_flags (BusOwner *owner,
182                      dbus_uint32_t flags)
183 {
184    owner->allow_replacement = 
185         (flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT) != FALSE;
186
187    owner->do_not_queue =
188         (flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) != FALSE;
189 }
190
191 static BusOwner *
192 bus_owner_new (BusService *service, 
193                DBusConnection *conn, 
194                dbus_uint32_t flags)
195 {
196   BusOwner *result;
197
198   result = _dbus_mem_pool_alloc (service->registry->owner_pool);
199   if (result != NULL)
200     {
201       result->refcount = 1;
202       /* don't ref the connection because we don't want
203          to block the connection from going away.
204          transactions take care of reffing the connection
205          but we need to use refcounting on the owner
206          so that the owner does not get freed before
207          we can deref the connection in the transaction
208        */
209       result->conn = conn;
210       result->service = service;
211
212       if (!bus_connection_add_owned_service (conn, service))
213         {
214           _dbus_mem_pool_dealloc (service->registry->owner_pool, result);
215           return NULL;
216         }
217         
218       bus_owner_set_flags (result, flags);
219     }
220   return result;
221 }
222
223 static BusOwner *
224 bus_owner_ref (BusOwner *owner)
225 {
226   _dbus_assert (owner->refcount > 0);
227   owner->refcount += 1;
228
229   return owner;
230 }
231
232 static void
233 bus_owner_unref  (BusOwner *owner)
234 {
235   _dbus_assert (owner->refcount > 0);
236   owner->refcount -= 1;
237
238   if (owner->refcount == 0)
239     {
240       bus_connection_remove_owned_service (owner->conn, owner->service);
241       _dbus_mem_pool_dealloc (owner->service->registry->owner_pool, owner);
242     }
243 }
244
245 BusService*
246 bus_registry_ensure (BusRegistry               *registry,
247                      const DBusString          *service_name,
248                      DBusConnection            *owner_connection_if_created,
249                      dbus_uint32_t              flags,
250                      BusTransaction            *transaction,
251                      DBusError                 *error)
252 {
253   BusService *service;
254
255   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
256   
257   _dbus_assert (owner_connection_if_created != NULL);
258   _dbus_assert (transaction != NULL);
259
260   service = _dbus_hash_table_lookup_string (registry->service_hash,
261                                             _dbus_string_get_const_data (service_name));
262   if (service != NULL)
263     return service;
264   
265   service = _dbus_mem_pool_alloc (registry->service_pool);
266   if (service == NULL)
267     {
268       BUS_SET_OOM (error);
269       return NULL;
270     }
271
272   service->registry = registry;  
273   service->refcount = 1;
274
275   _dbus_verbose ("copying string %p '%s' to service->name\n",
276                  service_name, _dbus_string_get_const_data (service_name));
277   if (!_dbus_string_copy_data (service_name, &service->name))
278     {
279       _dbus_mem_pool_dealloc (registry->service_pool, service);
280       BUS_SET_OOM (error);
281       return NULL;
282     }
283   _dbus_verbose ("copied string %p '%s' to '%s'\n",
284                  service_name, _dbus_string_get_const_data (service_name),
285                  service->name);
286
287   if (!bus_driver_send_service_owner_changed (service->name, 
288                                               NULL,
289                                               bus_connection_get_name (owner_connection_if_created),
290                                               transaction, error))
291     {
292       bus_service_unref (service);
293       return NULL;
294     }
295
296   if (!bus_activation_service_created (bus_context_get_activation (registry->context),
297                                        service->name, transaction, error))
298     {
299       bus_service_unref (service);
300       return NULL;
301     }
302   
303   if (!bus_service_add_owner (service, owner_connection_if_created, flags,
304                                               transaction, error))
305     {
306       bus_service_unref (service);
307       return NULL;
308     }
309   
310   if (!_dbus_hash_table_insert_string (registry->service_hash,
311                                        service->name,
312                                        service))
313     {
314       /* The add_owner gets reverted on transaction cancel */
315       BUS_SET_OOM (error);
316       return NULL;
317     }
318
319   return service;
320 }
321
322 void
323 bus_registry_foreach (BusRegistry               *registry,
324                       BusServiceForeachFunction  function,
325                       void                      *data)
326 {
327   DBusHashIter iter;
328   
329   _dbus_hash_iter_init (registry->service_hash, &iter);
330   while (_dbus_hash_iter_next (&iter))
331     {
332       BusService *service = _dbus_hash_iter_get_value (&iter);
333
334       (* function) (service, data);
335     }
336 }
337
338 dbus_bool_t
339 bus_registry_list_services (BusRegistry *registry,
340                             char      ***listp,
341                             int         *array_len)
342 {
343   int i, j, len;
344   char **retval;
345   DBusHashIter iter;
346    
347   len = _dbus_hash_table_get_n_entries (registry->service_hash);
348   retval = dbus_new (char *, len + 1);
349
350   if (retval == NULL)
351     return FALSE;
352
353   _dbus_hash_iter_init (registry->service_hash, &iter);
354   i = 0;
355   while (_dbus_hash_iter_next (&iter))
356     {
357       BusService *service = _dbus_hash_iter_get_value (&iter);
358
359       retval[i] = _dbus_strdup (service->name);
360       if (retval[i] == NULL)
361         goto error;
362
363       i++;
364     }
365
366   retval[i] = NULL;
367   
368   if (array_len)
369     *array_len = len;
370   
371   *listp = retval;
372   return TRUE;
373   
374  error:
375   for (j = 0; j < i; j++)
376     dbus_free (retval[j]);
377   dbus_free (retval);
378
379   return FALSE;
380 }
381
382 dbus_bool_t
383 bus_registry_acquire_service (BusRegistry      *registry,
384                               DBusConnection   *connection,
385                               const DBusString *service_name,
386                               dbus_uint32_t     flags,
387                               dbus_uint32_t    *result,
388                               BusTransaction   *transaction,
389                               DBusError        *error)
390 {
391   dbus_bool_t retval;
392   DBusConnection *old_owner_conn;
393   BusClientPolicy *policy;
394   BusService *service;
395   BusActivation  *activation;
396   BusSELinuxID *sid;
397   BusOwner *primary_owner;
398  
399   retval = FALSE;
400
401   if (!_dbus_validate_bus_name (service_name, 0,
402                                 _dbus_string_get_length (service_name)))
403     {
404       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
405                       "Requested bus name \"%s\" is not valid",
406                       _dbus_string_get_const_data (service_name));
407       
408       _dbus_verbose ("Attempt to acquire invalid service name\n");
409       
410       goto out;
411     }
412   
413   if (_dbus_string_get_byte (service_name, 0) == ':')
414     {
415       /* Not allowed; only base services can start with ':' */
416       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
417                       "Cannot acquire a service starting with ':' such as \"%s\"",
418                       _dbus_string_get_const_data (service_name));
419       
420       _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"",
421                      _dbus_string_get_const_data (service_name));
422       
423       goto out;
424     }
425
426   if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
427     {
428       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
429                       "Connection \"%s\" is not allowed to own the service \"%s\"because "
430                       "it is reserved for D-Bus' use only",
431                       bus_connection_is_active (connection) ?
432                       bus_connection_get_name (connection) :
433                       "(inactive)",
434                       DBUS_SERVICE_DBUS);
435       goto out;
436     }
437
438   policy = bus_connection_get_policy (connection);
439   _dbus_assert (policy != NULL);
440
441   /* Note that if sid is #NULL then the bus's own context gets used
442    * in bus_connection_selinux_allows_acquire_service()
443    */
444   sid = bus_selinux_id_table_lookup (registry->service_sid_table,
445                                                                          service_name);
446
447   if (!bus_selinux_allows_acquire_service (connection, sid,
448                                            _dbus_string_get_const_data (service_name), error))
449         {
450
451           if (dbus_error_is_set (error) &&
452           dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY))
453         {
454           goto out;
455         }
456
457           dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
458                                           "Connection \"%s\" is not allowed to own the service \"%s\" due "
459                                           "to SELinux policy",
460                                           bus_connection_is_active (connection) ?
461                                           bus_connection_get_name (connection) :
462                                           "(inactive)",
463                                           _dbus_string_get_const_data (service_name));
464           goto out;
465         }
466
467   if (!bus_client_policy_check_can_own (policy, service_name))
468         {
469           dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
470                                           "Connection \"%s\" is not allowed to own the service \"%s\" due "
471                                           "to security policies in the configuration file",
472                                           bus_connection_is_active (connection) ?
473                                           bus_connection_get_name (connection) :
474                                           "(inactive)",
475                                           _dbus_string_get_const_data (service_name));
476           goto out;
477         }
478
479   if (bus_connection_get_n_services_owned (connection) >=
480           bus_context_get_max_services_per_connection (registry->context))
481         {
482           dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
483                                           "Connection \"%s\" is not allowed to own more services "
484                                           "(increase limits in configuration file if required)",
485                                           bus_connection_is_active (connection) ?
486                                           bus_connection_get_name (connection) :
487                                           "(inactive)");
488           goto out;
489         }
490
491   service = bus_registry_lookup (registry, service_name);
492
493   if (service != NULL)
494         {
495           primary_owner = bus_service_get_primary_owner (service);
496           if (primary_owner != NULL)
497                 old_owner_conn = primary_owner->conn;
498           else
499                 old_owner_conn = NULL;
500         }
501   else
502         old_owner_conn = NULL;
503
504   if (service == NULL)
505         {
506           service = bus_registry_ensure (registry,
507                                                                          service_name, connection, flags,
508                                                                          transaction, error);
509           if (service == NULL)
510                 goto out;
511         }
512
513   primary_owner = bus_service_get_primary_owner (service);
514   if (primary_owner == NULL)
515         goto out;
516
517   if (old_owner_conn == NULL)
518         {
519           _dbus_assert (primary_owner->conn == connection);
520
521           *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
522         }
523   else if (old_owner_conn == connection)
524         {
525           bus_owner_set_flags (primary_owner, flags);
526           *result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
527         }
528   else if (((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
529                    !(bus_service_get_allow_replacement (service))) ||
530            ((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
531                    !(flags & DBUS_NAME_FLAG_REPLACE_EXISTING)))
532         {
533           DBusList *link;
534           BusOwner *temp_owner;
535         /* Since we can't be queued if we are already in the queue
536            remove us */
537
538           link = _bus_service_find_owner_link (service, connection);
539           if (link != NULL)
540                 {
541                   _dbus_list_unlink (&service->owners, link);
542                   temp_owner = (BusOwner *)link->data;
543                   bus_owner_unref (temp_owner);
544                   _dbus_list_free_link (link);
545                 }
546
547           *result = DBUS_REQUEST_NAME_REPLY_EXISTS;
548         }
549   else if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
550                    (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
551                 !(bus_service_get_allow_replacement (service))))
552         {
553           /* Queue the connection */
554           if (!bus_service_add_owner (service, connection,
555                                                                   flags,
556                                                                   transaction, error))
557                 goto out;
558
559           *result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
560         }
561   else
562         {
563           /* Replace the current owner */
564
565           /* We enqueue the new owner and remove the first one because
566            * that will cause NameAcquired and NameLost messages to
567            * be sent.
568            */
569
570           if (!bus_service_add_owner (service, connection,
571                                                                   flags,
572                                                                   transaction, error))
573                 goto out;
574
575           if (primary_owner->do_not_queue)
576                 {
577                   if (!bus_service_remove_owner (service, old_owner_conn,
578                                                                                  transaction, error))
579                         goto out;
580                 }
581           else
582                 {
583                   if (!bus_service_swap_owner (service, old_owner_conn,
584                                                                            transaction, error))
585                         goto out;
586                 }
587
588
589           _dbus_assert (connection == bus_service_get_primary_owner (service)->conn);
590           *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
591         }
592
593   activation = bus_context_get_activation (registry->context);
594   retval = bus_activation_send_pending_auto_activation_messages (activation,
595                                                                  service,
596                                                                  transaction,
597                                                                  error);
598
599  out:
600   return retval;
601 }
602
603 dbus_bool_t
604 bus_registry_acquire_kdbus_service (BusRegistry      *registry,
605                               DBusConnection   *connection,
606                               DBusMessage *message,
607                               dbus_uint32_t    *result,
608                               BusTransaction   *transaction,
609                               DBusError        *error)
610 {
611   dbus_bool_t retval;
612   BusService *service;
613   BusActivation  *activation;
614
615   DBusString service_name_real;
616   const DBusString *service_name = &service_name_real;
617   char* name;
618   dbus_uint32_t flags;
619   __u64 sender_id;
620
621   if (!dbus_message_get_args (message, error,
622                               DBUS_TYPE_STRING, &name,
623                               DBUS_TYPE_UINT32, &flags,
624                               DBUS_TYPE_INVALID))
625     return FALSE;
626
627   retval = FALSE;
628
629   _dbus_string_init_const (&service_name_real, name);
630
631   if (!_dbus_validate_bus_name (service_name, 0,
632                                 _dbus_string_get_length (service_name)))
633     {
634       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
635                       "Requested bus name \"%s\" is not valid",
636                       _dbus_string_get_const_data (service_name));
637
638       _dbus_verbose ("Attempt to acquire invalid service name\n");
639
640       goto out;
641     }
642
643   if (_dbus_string_get_byte (service_name, 0) == ':')
644     {
645       /* Not allowed; only base services can start with ':' */
646       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
647                       "Cannot acquire a service starting with ':' such as \"%s\"",
648                       _dbus_string_get_const_data (service_name));
649
650       _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"",
651                      _dbus_string_get_const_data (service_name));
652
653       goto out;
654     }
655
656   if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
657     {
658       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
659                       "Connection \"%s\" is not allowed to own the service \"%s\"because "
660                       "it is reserved for D-Bus' use only",
661                       bus_connection_is_active (connection) ?
662                       bus_connection_get_name (connection) :
663                       "(inactive)",
664                       DBUS_SERVICE_DBUS);
665       goto out;
666     }
667
668         service = bus_registry_lookup (registry, service_name);
669         if (service == NULL)
670         {
671                 service = bus_registry_ensure (registry, service_name, connection, flags,
672                                                                          transaction, error);  //adds daemon to service owners list - must be removed after right owner is set
673                 if (service == NULL)
674                   goto out;
675
676                 if(!kdbus_register_policy(service_name, connection))
677                 {
678                         dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
679                                                   "Connection is not allowed to own the service \"%s\" due to security policies in the configuration file",
680                                                   _dbus_string_get_const_data (service_name));
681                         goto out;
682                 }
683         }
684
685         sender_id = sender_name_to_id(dbus_message_get_sender(message), error);
686         if(dbus_error_is_set(error))
687                 return FALSE;
688
689         *result = kdbus_request_name(connection, service_name, flags, sender_id);
690         if(*result == -EPERM)
691         {
692                 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
693                                           "Connection is not allowed to own the service \"%s\" due to security policies in the configuration file",
694                                           _dbus_string_get_const_data (service_name));
695                 goto out;
696         }
697         else if(*result < 0)
698         {
699                 dbus_set_error (error, DBUS_ERROR_FAILED , "Name \"%s\" could not be acquired", name);
700                 goto out;
701         }
702
703         if((*result == DBUS_REQUEST_NAME_REPLY_IN_QUEUE) || (*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER))
704         {
705             DBusConnection* phantom;
706
707             phantom = create_phantom_connection(connection, dbus_message_get_sender(message));
708             if(phantom == NULL)
709                 goto out;
710             if (!bus_service_add_owner (service, phantom, flags, transaction, error))
711                 goto out;  /* todo FIXME what to do with phantom connection? look into create_phantom_connection for a clue*/
712             if(*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
713             {
714                 if(_bus_service_find_owner_link (service, connection))
715                 if (!bus_service_remove_owner (service, connection, transaction, error))
716                     goto out;  /* todo FIXME what to do with phantom connection? look into create_phantom_connection for a clue*/
717             }
718         }
719
720   activation = bus_context_get_activation (registry->context);
721   retval = bus_activation_send_pending_auto_activation_messages (activation,
722                                                                  service,
723                                                                  transaction,
724                                                                  error);
725   
726  out:
727   return retval;
728 }
729
730 dbus_bool_t
731 bus_registry_release_service (BusRegistry      *registry,
732                               DBusConnection   *connection,
733                               const DBusString *service_name,
734                               dbus_uint32_t    *result,
735                               BusTransaction   *transaction,
736                               DBusError        *error)
737 {
738   dbus_bool_t retval;
739   BusService *service;
740
741   retval = FALSE;
742
743   if (!_dbus_validate_bus_name (service_name, 0,
744                                 _dbus_string_get_length (service_name)))
745     {
746       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
747                       "Given bus name \"%s\" is not valid",
748                       _dbus_string_get_const_data (service_name));
749
750       _dbus_verbose ("Attempt to release invalid service name\n");
751
752       goto out;
753     }
754
755   if (_dbus_string_get_byte (service_name, 0) == ':')
756     {
757       /* Not allowed; the base service name cannot be created or released */
758       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
759                       "Cannot release a service starting with ':' such as \"%s\"",
760                       _dbus_string_get_const_data (service_name));
761
762       _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
763                      _dbus_string_get_const_data (service_name));
764
765       goto out;
766     }
767
768    if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
769     {
770       /* Not allowed; the base service name cannot be created or released */
771       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
772                       "Cannot release the %s service because it is owned by the bus",
773                      DBUS_SERVICE_DBUS);
774
775       _dbus_verbose ("Attempt to release service name \"%s\"",
776                      DBUS_SERVICE_DBUS);
777
778       goto out;
779     }
780
781   if(bus_context_is_kdbus(bus_transaction_get_context (transaction)))  //todo kdbus incl
782   {
783         __u64 sender_id;
784
785         sender_id = sender_name_to_id(dbus_message_get_sender((DBusMessage*)registry), error);
786         if(dbus_error_is_set(error))
787                 return FALSE;
788
789         *result = kdbus_release_name(connection, service_name, sender_id);
790   }
791   else
792   {
793           service = bus_registry_lookup (registry, service_name);
794
795           if (service == NULL)
796                 {
797                   *result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
798                 }
799           else if (!bus_service_has_owner (service, connection))
800                 {
801                   *result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
802                 }
803           else
804                 {
805                   if (!bus_service_remove_owner (service, connection,
806                                                                                  transaction, error))
807                         goto out;
808
809                   _dbus_assert (!bus_service_has_owner (service, connection));
810                   *result = DBUS_RELEASE_NAME_REPLY_RELEASED;
811                 }
812   }
813
814   retval = TRUE;
815
816  out:
817   return retval;
818 }
819
820 dbus_bool_t
821 bus_registry_set_service_context_table (BusRegistry   *registry,
822                                         DBusHashTable *table)
823 {
824   DBusHashTable *new_table;
825   DBusHashIter iter;
826   
827   new_table = bus_selinux_id_table_new ();
828   if (!new_table)
829     return FALSE;
830
831   _dbus_hash_iter_init (table, &iter);
832   while (_dbus_hash_iter_next (&iter))
833     {
834       const char *service = _dbus_hash_iter_get_string_key (&iter);
835       const char *context = _dbus_hash_iter_get_value (&iter);
836
837       if (!bus_selinux_id_table_insert (new_table,
838                                         service,
839                                         context))
840         return FALSE;
841     }
842   
843   if (registry->service_sid_table)
844     _dbus_hash_table_unref (registry->service_sid_table);
845   registry->service_sid_table = new_table;
846   return TRUE;
847 }
848
849 static void
850 bus_service_unlink_owner (BusService      *service,
851                           BusOwner        *owner)
852 {
853   _dbus_list_remove_last (&service->owners, owner);
854   bus_owner_unref (owner);
855 }
856
857 static void
858 bus_service_unlink (BusService *service)
859 {
860   _dbus_assert (service->owners == NULL);
861
862   /* the service may not be in the hash, if
863    * the failure causing transaction cancel
864    * was in the right place, but that's OK
865    */
866   _dbus_hash_table_remove_string (service->registry->service_hash,
867                                   service->name);
868   
869   bus_service_unref (service);
870 }
871
872 static void
873 bus_service_relink (BusService           *service,
874                     DBusPreallocatedHash *preallocated)
875 {
876   _dbus_assert (service->owners == NULL);
877   _dbus_assert (preallocated != NULL);
878
879   _dbus_hash_table_insert_string_preallocated (service->registry->service_hash,
880                                                preallocated,
881                                                service->name,
882                                                service);
883   
884   bus_service_ref (service);
885 }
886
887 /**
888  * Data used to represent an ownership cancellation in
889  * a bus transaction.
890  */
891 typedef struct
892 {
893   BusOwner *owner;            /**< the owner */
894   BusService *service;        /**< service to cancel ownership of */
895 } OwnershipCancelData;
896
897 static void
898 cancel_ownership (void *data)
899 {
900   OwnershipCancelData *d = data;
901
902   /* We don't need to send messages notifying of these
903    * changes, since we're reverting something that was
904    * cancelled (effectively never really happened)
905    */
906   bus_service_unlink_owner (d->service, d->owner);
907   
908   if (d->service->owners == NULL)
909     bus_service_unlink (d->service);
910 }
911
912 static void
913 free_ownership_cancel_data (void *data)
914 {
915   OwnershipCancelData *d = data;
916
917   dbus_connection_unref (d->owner->conn);
918   bus_owner_unref (d->owner);
919   bus_service_unref (d->service);
920   
921   dbus_free (d);
922 }
923
924 static dbus_bool_t
925 add_cancel_ownership_to_transaction (BusTransaction *transaction,
926                                      BusService     *service,
927                                      BusOwner       *owner)
928 {
929   OwnershipCancelData *d;
930
931   d = dbus_new (OwnershipCancelData, 1);
932   if (d == NULL)
933     return FALSE;
934   
935   d->service = service;
936   d->owner = owner;
937
938   if (!bus_transaction_add_cancel_hook (transaction, cancel_ownership, d,
939                                         free_ownership_cancel_data))
940     {
941       dbus_free (d);
942       return FALSE;
943     }
944
945   bus_service_ref (d->service);
946   bus_owner_ref (owner);
947   dbus_connection_ref (d->owner->conn);
948
949   return TRUE;
950 }
951
952 /* this function is self-cancelling if you cancel the transaction */
953 dbus_bool_t
954 bus_service_add_owner (BusService     *service,
955                        DBusConnection *connection,
956                        dbus_uint32_t  flags,
957                        BusTransaction *transaction,
958                        DBusError      *error)
959 {
960   BusOwner *bus_owner;
961   DBusList *bus_owner_link;
962   
963   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
964   
965  /* Send service acquired message first, OOM will result
966   * in cancelling the transaction
967   */
968   if (service->owners == NULL)
969     {
970       if (!bus_driver_send_service_acquired (connection, service->name, transaction, error))
971         return FALSE;
972     }
973   
974   bus_owner_link = _bus_service_find_owner_link (service, connection);
975   
976   if (bus_owner_link == NULL)
977     {
978       bus_owner = bus_owner_new (service, connection, flags);
979       if (bus_owner == NULL)
980         {
981           BUS_SET_OOM (error);
982           return FALSE;
983         }
984
985       bus_owner_set_flags (bus_owner, flags);
986       if (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || service->owners == NULL)
987         {
988           if (!_dbus_list_append (&service->owners,
989                                   bus_owner))
990             {
991               bus_owner_unref (bus_owner);
992               BUS_SET_OOM (error);
993               return FALSE;
994             }
995         }
996       else
997         {
998           if (!_dbus_list_insert_after (&service->owners,
999                                          _dbus_list_get_first_link (&service->owners),
1000                                          bus_owner))
1001             {
1002               bus_owner_unref (bus_owner);
1003               BUS_SET_OOM (error);
1004               return FALSE;
1005             }
1006         }      
1007     } 
1008   else 
1009     {
1010       /* Update the link since we are already in the queue
1011        * No need for operations that can produce OOM
1012        */
1013
1014       bus_owner = (BusOwner *) bus_owner_link->data;
1015       if (flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
1016         {
1017           DBusList *link;
1018           _dbus_list_unlink (&service->owners, bus_owner_link);
1019           link = _dbus_list_get_first_link (&service->owners);
1020           _dbus_assert (link != NULL);
1021           
1022           _dbus_list_insert_after_link (&service->owners, link, bus_owner_link);
1023         }
1024       
1025       bus_owner_set_flags (bus_owner, flags);
1026       return TRUE;
1027     }
1028
1029   if (!add_cancel_ownership_to_transaction (transaction,
1030                                             service,
1031                                             bus_owner))
1032     {
1033       bus_service_unlink_owner (service, bus_owner);
1034       BUS_SET_OOM (error);
1035       return FALSE;
1036     }
1037
1038   return TRUE;
1039 }
1040
1041 typedef struct
1042 {
1043   BusOwner       *owner;
1044   BusService     *service;
1045   BusOwner       *before_owner; /* restore to position before this connection in owners list */
1046   DBusList       *owner_link;
1047   DBusList       *service_link;
1048   DBusPreallocatedHash *hash_entry;
1049 } OwnershipRestoreData;
1050
1051 static void
1052 restore_ownership (void *data)
1053 {
1054   OwnershipRestoreData *d = data;
1055   DBusList *link;
1056
1057   _dbus_assert (d->service_link != NULL);
1058   _dbus_assert (d->owner_link != NULL);
1059   
1060   if (d->service->owners == NULL)
1061     {
1062       _dbus_assert (d->hash_entry != NULL);
1063       bus_service_relink (d->service, d->hash_entry);
1064     }
1065   else
1066     {
1067       _dbus_assert (d->hash_entry == NULL);
1068     }
1069   
1070   /* We don't need to send messages notifying of these
1071    * changes, since we're reverting something that was
1072    * cancelled (effectively never really happened)
1073    */
1074   link = _dbus_list_get_first_link (&d->service->owners);
1075   while (link != NULL)
1076     {
1077       if (link->data == d->before_owner)
1078         break;
1079
1080       link = _dbus_list_get_next_link (&d->service->owners, link);
1081     }
1082   
1083   _dbus_list_insert_before_link (&d->service->owners, link, d->owner_link);
1084
1085   /* Note that removing then restoring this changes the order in which
1086    * ServiceDeleted messages are sent on destruction of the
1087    * connection.  This should be OK as the only guarantee there is
1088    * that the base service is destroyed last, and we never even
1089    * tentatively remove the base service.
1090    */
1091   bus_connection_add_owned_service_link (d->owner->conn, d->service_link);
1092   
1093   d->hash_entry = NULL;
1094   d->service_link = NULL;
1095   d->owner_link = NULL;
1096 }
1097
1098 static void
1099 free_ownership_restore_data (void *data)
1100 {
1101   OwnershipRestoreData *d = data;
1102
1103   if (d->service_link)
1104     _dbus_list_free_link (d->service_link);
1105   if (d->owner_link)
1106     _dbus_list_free_link (d->owner_link);
1107   if (d->hash_entry)
1108     _dbus_hash_table_free_preallocated_entry (d->service->registry->service_hash,
1109                                               d->hash_entry);
1110
1111   dbus_connection_unref (d->owner->conn);
1112   bus_owner_unref (d->owner);
1113   bus_service_unref (d->service);
1114   
1115   dbus_free (d);
1116 }
1117
1118 static dbus_bool_t
1119 add_restore_ownership_to_transaction (BusTransaction *transaction,
1120                                       BusService     *service,
1121                                       BusOwner       *owner)
1122 {
1123   OwnershipRestoreData *d;
1124   DBusList *link;
1125
1126   d = dbus_new (OwnershipRestoreData, 1);
1127   if (d == NULL)
1128     return FALSE;
1129   
1130   d->service = service;
1131   d->owner = owner;
1132   d->service_link = _dbus_list_alloc_link (service);
1133   d->owner_link = _dbus_list_alloc_link (owner);
1134   d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash);
1135   
1136   bus_service_ref (d->service);
1137   bus_owner_ref (d->owner);
1138   dbus_connection_ref (d->owner->conn);
1139
1140   d->before_owner = NULL;
1141   link = _dbus_list_get_first_link (&service->owners);
1142   while (link != NULL)
1143     {
1144       if (link->data == owner)
1145         {
1146           link = _dbus_list_get_next_link (&service->owners, link);
1147
1148           if (link)
1149             d->before_owner = link->data;
1150
1151           break;
1152         }
1153       
1154       link = _dbus_list_get_next_link (&service->owners, link);
1155     }
1156   
1157   if (d->service_link == NULL ||
1158       d->owner_link == NULL ||
1159       d->hash_entry == NULL ||
1160       !bus_transaction_add_cancel_hook (transaction, restore_ownership, d,
1161                                         free_ownership_restore_data))
1162     {
1163       free_ownership_restore_data (d);
1164       return FALSE;
1165     }
1166   
1167   return TRUE;
1168 }
1169
1170 dbus_bool_t
1171 bus_service_swap_owner (BusService     *service,
1172                         DBusConnection *connection,
1173                         BusTransaction *transaction,
1174                         DBusError      *error)
1175 {
1176   DBusList *swap_link;
1177   BusOwner *primary_owner;
1178
1179   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1180
1181   /* We send out notifications before we do any work we
1182    * might have to undo if the notification-sending failed
1183    */
1184   
1185   /* Send service lost message */
1186   primary_owner = bus_service_get_primary_owner (service);
1187   if (primary_owner == NULL || primary_owner->conn != connection)
1188     _dbus_assert_not_reached ("Tried to swap a non primary owner");
1189
1190     
1191   if (!bus_driver_send_service_lost (connection, service->name,
1192                                      transaction, error))
1193     return FALSE;
1194
1195   if (service->owners == NULL)
1196     {
1197       _dbus_assert_not_reached ("Tried to swap owner of a service that has no owners");
1198     }
1199   else if (_dbus_list_length_is_one (&service->owners))
1200     {
1201       _dbus_assert_not_reached ("Tried to swap owner of a service that has no other owners in the queue");
1202     }
1203   else
1204     {
1205       DBusList *link;
1206       BusOwner *new_owner;
1207       DBusConnection *new_owner_conn;
1208       link = _dbus_list_get_first_link (&service->owners);
1209       _dbus_assert (link != NULL);
1210       link = _dbus_list_get_next_link (&service->owners, link);
1211       _dbus_assert (link != NULL);
1212
1213       new_owner = (BusOwner *)link->data;
1214       new_owner_conn = new_owner->conn;
1215
1216       if (!bus_driver_send_service_owner_changed (service->name,
1217                                                   bus_connection_get_name (connection),
1218                                                   bus_connection_get_name (new_owner_conn),
1219                                                   transaction, error))
1220         return FALSE;
1221
1222       /* This will be our new owner */
1223       if (!bus_driver_send_service_acquired (new_owner_conn,
1224                                              service->name,
1225                                              transaction,
1226                                              error))
1227         return FALSE;
1228     }
1229
1230   if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1231     {
1232       BUS_SET_OOM (error);
1233       return FALSE;
1234     }
1235
1236   /* unlink the primary and make it the second link */
1237   swap_link = _dbus_list_get_first_link (&service->owners);
1238   _dbus_list_unlink (&service->owners, swap_link);
1239
1240   _dbus_list_insert_after_link (&service->owners,
1241                                 _dbus_list_get_first_link (&service->owners),
1242                                 swap_link);
1243
1244   return TRUE;
1245 }
1246
1247 /* this function is self-cancelling if you cancel the transaction */
1248 dbus_bool_t
1249 bus_service_remove_owner (BusService     *service,
1250                           DBusConnection *connection,
1251                           BusTransaction *transaction,
1252                           DBusError      *error)
1253 {
1254   BusOwner *primary_owner;
1255   
1256   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1257   
1258   /* We send out notifications before we do any work we
1259    * might have to undo if the notification-sending failed
1260    */
1261   
1262   /* Send service lost message */
1263   primary_owner = bus_service_get_primary_owner (service);
1264   if (primary_owner != NULL && primary_owner->conn == connection)
1265     {
1266       if (!bus_driver_send_service_lost (connection, service->name,
1267                                          transaction, error))
1268         return FALSE;
1269     }
1270   else
1271     {
1272       /* if we are not the primary owner then just remove us from the queue */
1273       DBusList *link;
1274       BusOwner *temp_owner;
1275
1276       link = _bus_service_find_owner_link (service, connection);
1277       _dbus_list_unlink (&service->owners, link);
1278       temp_owner = (BusOwner *)link->data;
1279       bus_owner_unref (temp_owner); 
1280       _dbus_list_free_link (link);
1281
1282       return TRUE; 
1283     }
1284
1285   if (service->owners == NULL)
1286     {
1287       _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners");
1288     }
1289   else if (_dbus_list_length_is_one (&service->owners))
1290     {
1291       if (!bus_driver_send_service_owner_changed (service->name,
1292                                                   bus_connection_get_name (connection),
1293                                                   NULL,
1294                                                   transaction, error))
1295         return FALSE;
1296     }
1297   else
1298     {
1299       DBusList *link;
1300       BusOwner *new_owner;
1301       DBusConnection *new_owner_conn;
1302       link = _dbus_list_get_first_link (&service->owners);
1303       _dbus_assert (link != NULL);
1304       link = _dbus_list_get_next_link (&service->owners, link);
1305       _dbus_assert (link != NULL);
1306
1307       new_owner = (BusOwner *)link->data;
1308       new_owner_conn = new_owner->conn;
1309
1310       if (!bus_driver_send_service_owner_changed (service->name,
1311                                                   bus_connection_get_name (connection),
1312                                                   bus_connection_get_name (new_owner_conn),
1313                                                   transaction, error))
1314         return FALSE;
1315
1316       /* This will be our new owner */
1317       if (!bus_driver_send_service_acquired (new_owner_conn,
1318                                              service->name,
1319                                              transaction,
1320                                              error))
1321         return FALSE;
1322     }
1323
1324   if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1325     {
1326       BUS_SET_OOM (error);
1327       return FALSE;
1328     }
1329  
1330   bus_service_unlink_owner (service, primary_owner);
1331
1332   if (service->owners == NULL)
1333     bus_service_unlink (service);
1334
1335   return TRUE;
1336 }
1337
1338 BusService *
1339 bus_service_ref (BusService *service)
1340 {
1341   _dbus_assert (service->refcount > 0);
1342   
1343   service->refcount += 1;
1344
1345   return service;
1346 }
1347
1348 void
1349 bus_service_unref (BusService *service)
1350 {
1351   _dbus_assert (service->refcount > 0);
1352   
1353   service->refcount -= 1;
1354
1355   if (service->refcount == 0)
1356     {
1357       _dbus_assert (service->owners == NULL);
1358       
1359       dbus_free (service->name);
1360       _dbus_mem_pool_dealloc (service->registry->service_pool, service);
1361     }
1362 }
1363
1364 DBusConnection *
1365 bus_service_get_primary_owners_connection (BusService *service)
1366 {
1367   BusOwner *owner;
1368
1369   owner = bus_service_get_primary_owner (service);
1370
1371   if (owner != NULL)
1372     return owner->conn;
1373   else
1374     return NULL;
1375 }
1376
1377 BusOwner*
1378 bus_service_get_primary_owner (BusService *service)
1379 {
1380   return _dbus_list_get_first (&service->owners);
1381 }
1382
1383 const char*
1384 bus_service_get_name (BusService *service)
1385 {
1386   return service->name;
1387 }
1388
1389 dbus_bool_t
1390 bus_service_get_allow_replacement (BusService *service)
1391 {
1392   BusOwner *owner;
1393   DBusList *link;
1394  
1395   _dbus_assert (service->owners != NULL);
1396
1397   link = _dbus_list_get_first_link (&service->owners);
1398   owner = (BusOwner *) link->data;
1399
1400   return owner->allow_replacement;
1401 }
1402
1403 dbus_bool_t
1404 bus_service_has_owner (BusService     *service,
1405                        DBusConnection *connection)
1406 {
1407   DBusList *link;
1408
1409   link = _bus_service_find_owner_link (service, connection);
1410  
1411   if (link == NULL)
1412     return FALSE;
1413   else
1414     return TRUE;
1415 }
1416
1417 dbus_bool_t 
1418 bus_service_list_queued_owners (BusService *service,
1419                                 DBusList  **return_list,
1420                                 DBusError  *error)
1421 {
1422   DBusList *link;
1423
1424   _dbus_assert (*return_list == NULL);
1425
1426   link = _dbus_list_get_first_link (&service->owners);
1427   _dbus_assert (link != NULL);
1428   
1429   while (link != NULL)
1430     {
1431       BusOwner *owner;
1432       const char *uname;
1433
1434       owner = (BusOwner *) link->data;
1435       uname = bus_connection_get_name (owner->conn);
1436
1437       if (!_dbus_list_append (return_list, (char *)uname))
1438         goto oom;
1439
1440       link = _dbus_list_get_next_link (&service->owners, link);
1441     }
1442   
1443   return TRUE;
1444   
1445  oom:
1446   _dbus_list_clear (return_list);
1447   BUS_SET_OOM (error);
1448   return FALSE;
1449 }