[daemon-dev][lib-fix][lib-dev] ListQueuedOwners method in daemon, fixed strcpy issue...
[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                 if (!bus_service_remove_owner (service, connection, transaction, error))
714                     goto out;  /* todo FIXME what to do with phantom connection? look into create_phantom_connection for a clue*/
715         }
716
717   activation = bus_context_get_activation (registry->context);
718   retval = bus_activation_send_pending_auto_activation_messages (activation,
719                                                                  service,
720                                                                  transaction,
721                                                                  error);
722   
723  out:
724   return retval;
725 }
726
727 dbus_bool_t
728 bus_registry_release_service (BusRegistry      *registry,
729                               DBusConnection   *connection,
730                               const DBusString *service_name,
731                               dbus_uint32_t    *result,
732                               BusTransaction   *transaction,
733                               DBusError        *error)
734 {
735   dbus_bool_t retval;
736   BusService *service;
737
738   retval = FALSE;
739
740   if (!_dbus_validate_bus_name (service_name, 0,
741                                 _dbus_string_get_length (service_name)))
742     {
743       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
744                       "Given bus name \"%s\" is not valid",
745                       _dbus_string_get_const_data (service_name));
746
747       _dbus_verbose ("Attempt to release invalid service name\n");
748
749       goto out;
750     }
751
752   if (_dbus_string_get_byte (service_name, 0) == ':')
753     {
754       /* Not allowed; the base service name cannot be created or released */
755       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
756                       "Cannot release a service starting with ':' such as \"%s\"",
757                       _dbus_string_get_const_data (service_name));
758
759       _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
760                      _dbus_string_get_const_data (service_name));
761
762       goto out;
763     }
764
765    if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
766     {
767       /* Not allowed; the base service name cannot be created or released */
768       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
769                       "Cannot release the %s service because it is owned by the bus",
770                      DBUS_SERVICE_DBUS);
771
772       _dbus_verbose ("Attempt to release service name \"%s\"",
773                      DBUS_SERVICE_DBUS);
774
775       goto out;
776     }
777
778   if(bus_context_is_kdbus(bus_transaction_get_context (transaction)))  //todo kdbus incl
779   {
780         __u64 sender_id;
781
782         sender_id = sender_name_to_id(dbus_message_get_sender((DBusMessage*)registry), error);
783         if(dbus_error_is_set(error))
784                 return FALSE;
785
786         *result = kdbus_release_name(connection, service_name, sender_id);
787   }
788   else
789   {
790           service = bus_registry_lookup (registry, service_name);
791
792           if (service == NULL)
793                 {
794                   *result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
795                 }
796           else if (!bus_service_has_owner (service, connection))
797                 {
798                   *result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
799                 }
800           else
801                 {
802                   if (!bus_service_remove_owner (service, connection,
803                                                                                  transaction, error))
804                         goto out;
805
806                   _dbus_assert (!bus_service_has_owner (service, connection));
807                   *result = DBUS_RELEASE_NAME_REPLY_RELEASED;
808                 }
809   }
810
811   retval = TRUE;
812
813  out:
814   return retval;
815 }
816
817 dbus_bool_t
818 bus_registry_set_service_context_table (BusRegistry   *registry,
819                                         DBusHashTable *table)
820 {
821   DBusHashTable *new_table;
822   DBusHashIter iter;
823   
824   new_table = bus_selinux_id_table_new ();
825   if (!new_table)
826     return FALSE;
827
828   _dbus_hash_iter_init (table, &iter);
829   while (_dbus_hash_iter_next (&iter))
830     {
831       const char *service = _dbus_hash_iter_get_string_key (&iter);
832       const char *context = _dbus_hash_iter_get_value (&iter);
833
834       if (!bus_selinux_id_table_insert (new_table,
835                                         service,
836                                         context))
837         return FALSE;
838     }
839   
840   if (registry->service_sid_table)
841     _dbus_hash_table_unref (registry->service_sid_table);
842   registry->service_sid_table = new_table;
843   return TRUE;
844 }
845
846 static void
847 bus_service_unlink_owner (BusService      *service,
848                           BusOwner        *owner)
849 {
850   _dbus_list_remove_last (&service->owners, owner);
851   bus_owner_unref (owner);
852 }
853
854 static void
855 bus_service_unlink (BusService *service)
856 {
857   _dbus_assert (service->owners == NULL);
858
859   /* the service may not be in the hash, if
860    * the failure causing transaction cancel
861    * was in the right place, but that's OK
862    */
863   _dbus_hash_table_remove_string (service->registry->service_hash,
864                                   service->name);
865   
866   bus_service_unref (service);
867 }
868
869 static void
870 bus_service_relink (BusService           *service,
871                     DBusPreallocatedHash *preallocated)
872 {
873   _dbus_assert (service->owners == NULL);
874   _dbus_assert (preallocated != NULL);
875
876   _dbus_hash_table_insert_string_preallocated (service->registry->service_hash,
877                                                preallocated,
878                                                service->name,
879                                                service);
880   
881   bus_service_ref (service);
882 }
883
884 /**
885  * Data used to represent an ownership cancellation in
886  * a bus transaction.
887  */
888 typedef struct
889 {
890   BusOwner *owner;            /**< the owner */
891   BusService *service;        /**< service to cancel ownership of */
892 } OwnershipCancelData;
893
894 static void
895 cancel_ownership (void *data)
896 {
897   OwnershipCancelData *d = data;
898
899   /* We don't need to send messages notifying of these
900    * changes, since we're reverting something that was
901    * cancelled (effectively never really happened)
902    */
903   bus_service_unlink_owner (d->service, d->owner);
904   
905   if (d->service->owners == NULL)
906     bus_service_unlink (d->service);
907 }
908
909 static void
910 free_ownership_cancel_data (void *data)
911 {
912   OwnershipCancelData *d = data;
913
914   dbus_connection_unref (d->owner->conn);
915   bus_owner_unref (d->owner);
916   bus_service_unref (d->service);
917   
918   dbus_free (d);
919 }
920
921 static dbus_bool_t
922 add_cancel_ownership_to_transaction (BusTransaction *transaction,
923                                      BusService     *service,
924                                      BusOwner       *owner)
925 {
926   OwnershipCancelData *d;
927
928   d = dbus_new (OwnershipCancelData, 1);
929   if (d == NULL)
930     return FALSE;
931   
932   d->service = service;
933   d->owner = owner;
934
935   if (!bus_transaction_add_cancel_hook (transaction, cancel_ownership, d,
936                                         free_ownership_cancel_data))
937     {
938       dbus_free (d);
939       return FALSE;
940     }
941
942   bus_service_ref (d->service);
943   bus_owner_ref (owner);
944   dbus_connection_ref (d->owner->conn);
945
946   return TRUE;
947 }
948
949 /* this function is self-cancelling if you cancel the transaction */
950 dbus_bool_t
951 bus_service_add_owner (BusService     *service,
952                        DBusConnection *connection,
953                        dbus_uint32_t  flags,
954                        BusTransaction *transaction,
955                        DBusError      *error)
956 {
957   BusOwner *bus_owner;
958   DBusList *bus_owner_link;
959   
960   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
961   
962  /* Send service acquired message first, OOM will result
963   * in cancelling the transaction
964   */
965   if (service->owners == NULL)
966     {
967       if (!bus_driver_send_service_acquired (connection, service->name, transaction, error))
968         return FALSE;
969     }
970   
971   bus_owner_link = _bus_service_find_owner_link (service, connection);
972   
973   if (bus_owner_link == NULL)
974     {
975       bus_owner = bus_owner_new (service, connection, flags);
976       if (bus_owner == NULL)
977         {
978           BUS_SET_OOM (error);
979           return FALSE;
980         }
981
982       bus_owner_set_flags (bus_owner, flags);
983       if (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || service->owners == NULL)
984         {
985           if (!_dbus_list_append (&service->owners,
986                                   bus_owner))
987             {
988               bus_owner_unref (bus_owner);
989               BUS_SET_OOM (error);
990               return FALSE;
991             }
992         }
993       else
994         {
995           if (!_dbus_list_insert_after (&service->owners,
996                                          _dbus_list_get_first_link (&service->owners),
997                                          bus_owner))
998             {
999               bus_owner_unref (bus_owner);
1000               BUS_SET_OOM (error);
1001               return FALSE;
1002             }
1003         }      
1004     } 
1005   else 
1006     {
1007       /* Update the link since we are already in the queue
1008        * No need for operations that can produce OOM
1009        */
1010
1011       bus_owner = (BusOwner *) bus_owner_link->data;
1012       if (flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
1013         {
1014           DBusList *link;
1015           _dbus_list_unlink (&service->owners, bus_owner_link);
1016           link = _dbus_list_get_first_link (&service->owners);
1017           _dbus_assert (link != NULL);
1018           
1019           _dbus_list_insert_after_link (&service->owners, link, bus_owner_link);
1020         }
1021       
1022       bus_owner_set_flags (bus_owner, flags);
1023       return TRUE;
1024     }
1025
1026   if (!add_cancel_ownership_to_transaction (transaction,
1027                                             service,
1028                                             bus_owner))
1029     {
1030       bus_service_unlink_owner (service, bus_owner);
1031       BUS_SET_OOM (error);
1032       return FALSE;
1033     }
1034
1035   return TRUE;
1036 }
1037
1038 typedef struct
1039 {
1040   BusOwner       *owner;
1041   BusService     *service;
1042   BusOwner       *before_owner; /* restore to position before this connection in owners list */
1043   DBusList       *owner_link;
1044   DBusList       *service_link;
1045   DBusPreallocatedHash *hash_entry;
1046 } OwnershipRestoreData;
1047
1048 static void
1049 restore_ownership (void *data)
1050 {
1051   OwnershipRestoreData *d = data;
1052   DBusList *link;
1053
1054   _dbus_assert (d->service_link != NULL);
1055   _dbus_assert (d->owner_link != NULL);
1056   
1057   if (d->service->owners == NULL)
1058     {
1059       _dbus_assert (d->hash_entry != NULL);
1060       bus_service_relink (d->service, d->hash_entry);
1061     }
1062   else
1063     {
1064       _dbus_assert (d->hash_entry == NULL);
1065     }
1066   
1067   /* We don't need to send messages notifying of these
1068    * changes, since we're reverting something that was
1069    * cancelled (effectively never really happened)
1070    */
1071   link = _dbus_list_get_first_link (&d->service->owners);
1072   while (link != NULL)
1073     {
1074       if (link->data == d->before_owner)
1075         break;
1076
1077       link = _dbus_list_get_next_link (&d->service->owners, link);
1078     }
1079   
1080   _dbus_list_insert_before_link (&d->service->owners, link, d->owner_link);
1081
1082   /* Note that removing then restoring this changes the order in which
1083    * ServiceDeleted messages are sent on destruction of the
1084    * connection.  This should be OK as the only guarantee there is
1085    * that the base service is destroyed last, and we never even
1086    * tentatively remove the base service.
1087    */
1088   bus_connection_add_owned_service_link (d->owner->conn, d->service_link);
1089   
1090   d->hash_entry = NULL;
1091   d->service_link = NULL;
1092   d->owner_link = NULL;
1093 }
1094
1095 static void
1096 free_ownership_restore_data (void *data)
1097 {
1098   OwnershipRestoreData *d = data;
1099
1100   if (d->service_link)
1101     _dbus_list_free_link (d->service_link);
1102   if (d->owner_link)
1103     _dbus_list_free_link (d->owner_link);
1104   if (d->hash_entry)
1105     _dbus_hash_table_free_preallocated_entry (d->service->registry->service_hash,
1106                                               d->hash_entry);
1107
1108   dbus_connection_unref (d->owner->conn);
1109   bus_owner_unref (d->owner);
1110   bus_service_unref (d->service);
1111   
1112   dbus_free (d);
1113 }
1114
1115 static dbus_bool_t
1116 add_restore_ownership_to_transaction (BusTransaction *transaction,
1117                                       BusService     *service,
1118                                       BusOwner       *owner)
1119 {
1120   OwnershipRestoreData *d;
1121   DBusList *link;
1122
1123   d = dbus_new (OwnershipRestoreData, 1);
1124   if (d == NULL)
1125     return FALSE;
1126   
1127   d->service = service;
1128   d->owner = owner;
1129   d->service_link = _dbus_list_alloc_link (service);
1130   d->owner_link = _dbus_list_alloc_link (owner);
1131   d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash);
1132   
1133   bus_service_ref (d->service);
1134   bus_owner_ref (d->owner);
1135   dbus_connection_ref (d->owner->conn);
1136
1137   d->before_owner = NULL;
1138   link = _dbus_list_get_first_link (&service->owners);
1139   while (link != NULL)
1140     {
1141       if (link->data == owner)
1142         {
1143           link = _dbus_list_get_next_link (&service->owners, link);
1144
1145           if (link)
1146             d->before_owner = link->data;
1147
1148           break;
1149         }
1150       
1151       link = _dbus_list_get_next_link (&service->owners, link);
1152     }
1153   
1154   if (d->service_link == NULL ||
1155       d->owner_link == NULL ||
1156       d->hash_entry == NULL ||
1157       !bus_transaction_add_cancel_hook (transaction, restore_ownership, d,
1158                                         free_ownership_restore_data))
1159     {
1160       free_ownership_restore_data (d);
1161       return FALSE;
1162     }
1163   
1164   return TRUE;
1165 }
1166
1167 dbus_bool_t
1168 bus_service_swap_owner (BusService     *service,
1169                         DBusConnection *connection,
1170                         BusTransaction *transaction,
1171                         DBusError      *error)
1172 {
1173   DBusList *swap_link;
1174   BusOwner *primary_owner;
1175
1176   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1177
1178   /* We send out notifications before we do any work we
1179    * might have to undo if the notification-sending failed
1180    */
1181   
1182   /* Send service lost message */
1183   primary_owner = bus_service_get_primary_owner (service);
1184   if (primary_owner == NULL || primary_owner->conn != connection)
1185     _dbus_assert_not_reached ("Tried to swap a non primary owner");
1186
1187     
1188   if (!bus_driver_send_service_lost (connection, service->name,
1189                                      transaction, error))
1190     return FALSE;
1191
1192   if (service->owners == NULL)
1193     {
1194       _dbus_assert_not_reached ("Tried to swap owner of a service that has no owners");
1195     }
1196   else if (_dbus_list_length_is_one (&service->owners))
1197     {
1198       _dbus_assert_not_reached ("Tried to swap owner of a service that has no other owners in the queue");
1199     }
1200   else
1201     {
1202       DBusList *link;
1203       BusOwner *new_owner;
1204       DBusConnection *new_owner_conn;
1205       link = _dbus_list_get_first_link (&service->owners);
1206       _dbus_assert (link != NULL);
1207       link = _dbus_list_get_next_link (&service->owners, link);
1208       _dbus_assert (link != NULL);
1209
1210       new_owner = (BusOwner *)link->data;
1211       new_owner_conn = new_owner->conn;
1212
1213       if (!bus_driver_send_service_owner_changed (service->name,
1214                                                   bus_connection_get_name (connection),
1215                                                   bus_connection_get_name (new_owner_conn),
1216                                                   transaction, error))
1217         return FALSE;
1218
1219       /* This will be our new owner */
1220       if (!bus_driver_send_service_acquired (new_owner_conn,
1221                                              service->name,
1222                                              transaction,
1223                                              error))
1224         return FALSE;
1225     }
1226
1227   if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1228     {
1229       BUS_SET_OOM (error);
1230       return FALSE;
1231     }
1232
1233   /* unlink the primary and make it the second link */
1234   swap_link = _dbus_list_get_first_link (&service->owners);
1235   _dbus_list_unlink (&service->owners, swap_link);
1236
1237   _dbus_list_insert_after_link (&service->owners,
1238                                 _dbus_list_get_first_link (&service->owners),
1239                                 swap_link);
1240
1241   return TRUE;
1242 }
1243
1244 /* this function is self-cancelling if you cancel the transaction */
1245 dbus_bool_t
1246 bus_service_remove_owner (BusService     *service,
1247                           DBusConnection *connection,
1248                           BusTransaction *transaction,
1249                           DBusError      *error)
1250 {
1251   BusOwner *primary_owner;
1252   
1253   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1254   
1255   /* We send out notifications before we do any work we
1256    * might have to undo if the notification-sending failed
1257    */
1258   
1259   /* Send service lost message */
1260   primary_owner = bus_service_get_primary_owner (service);
1261   if (primary_owner != NULL && primary_owner->conn == connection)
1262     {
1263       if (!bus_driver_send_service_lost (connection, service->name,
1264                                          transaction, error))
1265         return FALSE;
1266     }
1267   else
1268     {
1269       /* if we are not the primary owner then just remove us from the queue */
1270       DBusList *link;
1271       BusOwner *temp_owner;
1272
1273       link = _bus_service_find_owner_link (service, connection);
1274       _dbus_list_unlink (&service->owners, link);
1275       temp_owner = (BusOwner *)link->data;
1276       bus_owner_unref (temp_owner); 
1277       _dbus_list_free_link (link);
1278
1279       return TRUE; 
1280     }
1281
1282   if (service->owners == NULL)
1283     {
1284       _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners");
1285     }
1286   else if (_dbus_list_length_is_one (&service->owners))
1287     {
1288       if (!bus_driver_send_service_owner_changed (service->name,
1289                                                   bus_connection_get_name (connection),
1290                                                   NULL,
1291                                                   transaction, error))
1292         return FALSE;
1293     }
1294   else
1295     {
1296       DBusList *link;
1297       BusOwner *new_owner;
1298       DBusConnection *new_owner_conn;
1299       link = _dbus_list_get_first_link (&service->owners);
1300       _dbus_assert (link != NULL);
1301       link = _dbus_list_get_next_link (&service->owners, link);
1302       _dbus_assert (link != NULL);
1303
1304       new_owner = (BusOwner *)link->data;
1305       new_owner_conn = new_owner->conn;
1306
1307       if (!bus_driver_send_service_owner_changed (service->name,
1308                                                   bus_connection_get_name (connection),
1309                                                   bus_connection_get_name (new_owner_conn),
1310                                                   transaction, error))
1311         return FALSE;
1312
1313       /* This will be our new owner */
1314       if (!bus_driver_send_service_acquired (new_owner_conn,
1315                                              service->name,
1316                                              transaction,
1317                                              error))
1318         return FALSE;
1319     }
1320
1321   if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1322     {
1323       BUS_SET_OOM (error);
1324       return FALSE;
1325     }
1326  
1327   bus_service_unlink_owner (service, primary_owner);
1328
1329   if (service->owners == NULL)
1330     bus_service_unlink (service);
1331
1332   return TRUE;
1333 }
1334
1335 BusService *
1336 bus_service_ref (BusService *service)
1337 {
1338   _dbus_assert (service->refcount > 0);
1339   
1340   service->refcount += 1;
1341
1342   return service;
1343 }
1344
1345 void
1346 bus_service_unref (BusService *service)
1347 {
1348   _dbus_assert (service->refcount > 0);
1349   
1350   service->refcount -= 1;
1351
1352   if (service->refcount == 0)
1353     {
1354       _dbus_assert (service->owners == NULL);
1355       
1356       dbus_free (service->name);
1357       _dbus_mem_pool_dealloc (service->registry->service_pool, service);
1358     }
1359 }
1360
1361 DBusConnection *
1362 bus_service_get_primary_owners_connection (BusService *service)
1363 {
1364   BusOwner *owner;
1365
1366   owner = bus_service_get_primary_owner (service);
1367
1368   if (owner != NULL)
1369     return owner->conn;
1370   else
1371     return NULL;
1372 }
1373
1374 BusOwner*
1375 bus_service_get_primary_owner (BusService *service)
1376 {
1377   return _dbus_list_get_first (&service->owners);
1378 }
1379
1380 const char*
1381 bus_service_get_name (BusService *service)
1382 {
1383   return service->name;
1384 }
1385
1386 dbus_bool_t
1387 bus_service_get_allow_replacement (BusService *service)
1388 {
1389   BusOwner *owner;
1390   DBusList *link;
1391  
1392   _dbus_assert (service->owners != NULL);
1393
1394   link = _dbus_list_get_first_link (&service->owners);
1395   owner = (BusOwner *) link->data;
1396
1397   return owner->allow_replacement;
1398 }
1399
1400 dbus_bool_t
1401 bus_service_has_owner (BusService     *service,
1402                        DBusConnection *connection)
1403 {
1404   DBusList *link;
1405
1406   link = _bus_service_find_owner_link (service, connection);
1407  
1408   if (link == NULL)
1409     return FALSE;
1410   else
1411     return TRUE;
1412 }
1413
1414 dbus_bool_t 
1415 bus_service_list_queued_owners (BusService *service,
1416                                 DBusList  **return_list,
1417                                 DBusError  *error)
1418 {
1419   DBusList *link;
1420
1421   _dbus_assert (*return_list == NULL);
1422
1423   link = _dbus_list_get_first_link (&service->owners);
1424   _dbus_assert (link != NULL);
1425   
1426   while (link != NULL)
1427     {
1428       BusOwner *owner;
1429       const char *uname;
1430
1431       owner = (BusOwner *) link->data;
1432       uname = bus_connection_get_name (owner->conn);
1433
1434       if (!_dbus_list_append (return_list, (char *)uname))
1435         goto oom;
1436
1437       link = _dbus_list_get_next_link (&service->owners, link);
1438     }
1439   
1440   return TRUE;
1441   
1442  oom:
1443   _dbus_list_clear (return_list);
1444   BUS_SET_OOM (error);
1445   return FALSE;
1446 }