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