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