• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "config.h"
2 
3 #include <string.h>
4 #include <stdlib.h>
5 
6 #include <gstdio.h>
7 #include <gio/gio.h>
8 #include <gio/gunixsocketaddress.h>
9 #include "gdbusdaemon.h"
10 #include "glibintl.h"
11 
12 #include "gdbus-daemon-generated.h"
13 
14 #define DBUS_SERVICE_NAME  "org.freedesktop.DBus"
15 
16 /* Owner flags */
17 #define DBUS_NAME_FLAG_ALLOW_REPLACEMENT 0x1 /**< Allow another service to become the primary owner if requested */
18 #define DBUS_NAME_FLAG_REPLACE_EXISTING  0x2 /**< Request to replace the current primary owner */
19 #define DBUS_NAME_FLAG_DO_NOT_QUEUE      0x4 /**< If we can not become the primary owner do not place us in the queue */
20 
21 /* Replies to request for a name */
22 #define DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER  1 /**< Service has become the primary owner of the requested name */
23 #define DBUS_REQUEST_NAME_REPLY_IN_QUEUE       2 /**< Service could not become the primary owner and has been placed in the queue */
24 #define DBUS_REQUEST_NAME_REPLY_EXISTS         3 /**< Service is already in the queue */
25 #define DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER  4 /**< Service is already the primary owner */
26 
27 /* Replies to releasing a name */
28 #define DBUS_RELEASE_NAME_REPLY_RELEASED        1 /**< Service was released from the given name */
29 #define DBUS_RELEASE_NAME_REPLY_NON_EXISTENT    2 /**< The given name does not exist on the bus */
30 #define DBUS_RELEASE_NAME_REPLY_NOT_OWNER       3 /**< Service is not an owner of the given name */
31 
32 /* Replies to service starts */
33 #define DBUS_START_REPLY_SUCCESS         1 /**< Service was auto started */
34 #define DBUS_START_REPLY_ALREADY_RUNNING 2 /**< Service was already running */
35 
36 #define IDLE_TIMEOUT_MSEC 3000
37 
38 struct _GDBusDaemon
39 {
40   _GFreedesktopDBusSkeleton parent_instance;
41 
42   gchar *address;
43   guint timeout;
44   gchar *tmpdir;
45   GDBusServer *server;
46   gchar *guid;
47   GHashTable *clients;
48   GHashTable *names;
49   guint32 next_major_id;
50   guint32 next_minor_id;
51 };
52 
53 struct _GDBusDaemonClass
54 {
55   _GFreedesktopDBusSkeletonClass parent_class;
56 };
57 
58 enum {
59   PROP_0,
60   PROP_ADDRESS,
61 };
62 
63 enum
64 {
65   SIGNAL_IDLE_TIMEOUT,
66   NR_SIGNALS
67 };
68 
69 static guint g_dbus_daemon_signals[NR_SIGNALS];
70 
71 
72 static void initable_iface_init      (GInitableIface         *initable_iface);
73 static void g_dbus_daemon_iface_init (_GFreedesktopDBusIface *iface);
74 
75 #define g_dbus_daemon_get_type _g_dbus_daemon_get_type
76 G_DEFINE_TYPE_WITH_CODE (GDBusDaemon, g_dbus_daemon, _G_TYPE_FREEDESKTOP_DBUS_SKELETON,
77 			 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
78 			 G_IMPLEMENT_INTERFACE (_G_TYPE_FREEDESKTOP_DBUS, g_dbus_daemon_iface_init))
79 
80 typedef struct {
81   GDBusDaemon *daemon;
82   char *id;
83   GDBusConnection *connection;
84   GList *matches;
85 } Client;
86 
87 typedef struct {
88   Client *client;
89   guint32 flags;
90 } NameOwner;
91 
92 typedef struct {
93   int refcount;
94 
95   char *name;
96   GDBusDaemon *daemon;
97 
98   NameOwner *owner;
99   GList *queue;
100 } Name;
101 
102 enum {
103   MATCH_ELEMENT_TYPE,
104   MATCH_ELEMENT_SENDER,
105   MATCH_ELEMENT_INTERFACE,
106   MATCH_ELEMENT_MEMBER,
107   MATCH_ELEMENT_PATH,
108   MATCH_ELEMENT_PATH_NAMESPACE,
109   MATCH_ELEMENT_DESTINATION,
110   MATCH_ELEMENT_ARG0NAMESPACE,
111   MATCH_ELEMENT_EAVESDROP,
112   MATCH_ELEMENT_ARGN,
113   MATCH_ELEMENT_ARGNPATH,
114 };
115 
116 typedef struct {
117   guint16 type;
118   guint16 arg;
119   char *value;
120 } MatchElement;
121 
122 typedef struct {
123   gboolean eavesdrop;
124   GDBusMessageType type;
125   int n_elements;
126   MatchElement *elements;
127 } Match;
128 
129 static GDBusMessage *filter_function   (GDBusConnection *connection,
130 					GDBusMessage    *message,
131 					gboolean         incoming,
132 					gpointer         user_data);
133 static void          connection_closed (GDBusConnection *connection,
134 					gboolean         remote_peer_vanished,
135 					GError          *error,
136 					Client          *client);
137 
138 static NameOwner *
name_owner_new(Client * client,guint32 flags)139 name_owner_new (Client *client, guint32 flags)
140 {
141   NameOwner *owner;
142 
143   owner = g_new0 (NameOwner, 1);
144   owner->client = client;
145   owner->flags = flags;
146   return owner;
147 }
148 
149 static void
name_owner_free(NameOwner * owner)150 name_owner_free (NameOwner *owner)
151 {
152   g_free (owner);
153 }
154 
155 static Name *
name_new(GDBusDaemon * daemon,const char * str)156 name_new (GDBusDaemon *daemon, const char *str)
157 {
158   Name *name;
159 
160   name = g_new0 (Name, 1);
161   name->refcount = 1;
162   name->daemon = daemon;
163   name->name = g_strdup (str);
164 
165   g_hash_table_insert (daemon->names, name->name, name);
166 
167   return name;
168 }
169 
170 static Name *
name_ref(Name * name)171 name_ref (Name *name)
172 {
173   g_assert (name->refcount > 0);
174   name->refcount++;
175   return name;
176 }
177 
178 static void
name_unref(Name * name)179 name_unref (Name *name)
180 {
181   g_assert (name->refcount > 0);
182   if (--name->refcount == 0)
183     {
184       g_hash_table_remove (name->daemon->names, name->name);
185       g_free (name->name);
186       g_free (name);
187     }
188 }
189 
190 static Name *
name_ensure(GDBusDaemon * daemon,const char * str)191 name_ensure (GDBusDaemon *daemon, const char *str)
192 {
193   Name *name;
194 
195   name = g_hash_table_lookup (daemon->names, str);
196 
197   if (name != NULL)
198     return name_ref (name);
199   return name_new (daemon, str);
200 }
201 
202 static Name *
name_lookup(GDBusDaemon * daemon,const char * str)203 name_lookup (GDBusDaemon *daemon, const char *str)
204 {
205   return g_hash_table_lookup (daemon->names, str);
206 }
207 
208 static gboolean
is_key(const char * key_start,const char * key_end,const char * value)209 is_key (const char *key_start, const char *key_end, const char *value)
210 {
211   gsize len = strlen (value);
212 
213   g_assert (key_end >= key_start);
214   if (len != (gsize) (key_end - key_start))
215     return FALSE;
216 
217   return strncmp (key_start, value, len) == 0;
218 }
219 
220 static gboolean
parse_key(MatchElement * element,const char * key_start,const char * key_end)221 parse_key (MatchElement *element, const char *key_start, const char *key_end)
222 {
223   gboolean res = TRUE;
224 
225   if (is_key (key_start, key_end, "type"))
226     {
227       element->type = MATCH_ELEMENT_TYPE;
228     }
229   else if (is_key (key_start, key_end, "sender"))
230     {
231       element->type = MATCH_ELEMENT_SENDER;
232     }
233   else if (is_key (key_start, key_end, "interface"))
234     {
235       element->type = MATCH_ELEMENT_INTERFACE;
236     }
237   else if (is_key (key_start, key_end, "member"))
238     {
239       element->type = MATCH_ELEMENT_MEMBER;
240     }
241   else if (is_key (key_start, key_end, "path"))
242     {
243       element->type = MATCH_ELEMENT_PATH;
244     }
245   else if (is_key (key_start, key_end, "path_namespace"))
246     {
247       element->type = MATCH_ELEMENT_PATH_NAMESPACE;
248     }
249   else if (is_key (key_start, key_end, "destination"))
250     {
251       element->type = MATCH_ELEMENT_DESTINATION;
252     }
253   else if (is_key (key_start, key_end, "arg0namespace"))
254     {
255       element->type = MATCH_ELEMENT_ARG0NAMESPACE;
256     }
257   else if (is_key (key_start, key_end, "eavesdrop"))
258     {
259       element->type = MATCH_ELEMENT_EAVESDROP;
260     }
261   else if (key_end - key_start > 3 && is_key (key_start, key_start + 3, "arg"))
262     {
263       const char *digits = key_start + 3;
264       const char *end_digits = digits;
265 
266       while (end_digits < key_end && g_ascii_isdigit (*end_digits))
267 	end_digits++;
268 
269       if (end_digits == key_end) /* argN */
270 	{
271 	  element->type = MATCH_ELEMENT_ARGN;
272 	  element->arg = atoi (digits);
273 	}
274       else if (is_key (end_digits, key_end, "path")) /* argNpath */
275 	{
276 	  element->type = MATCH_ELEMENT_ARGNPATH;
277 	  element->arg = atoi (digits);
278 	}
279       else
280 	res = FALSE;
281     }
282   else
283     res = FALSE;
284 
285   return res;
286 }
287 
288 static const char *
parse_value(MatchElement * element,const char * s)289 parse_value (MatchElement *element, const char *s)
290 {
291   char quote_char;
292   GString *value;
293 
294   value = g_string_new ("");
295 
296   quote_char = 0;
297 
298   for (;*s; s++)
299     {
300       if (quote_char == 0)
301 	{
302 	  switch (*s)
303 	    {
304 	    case '\'':
305 	      quote_char = '\'';
306 	      break;
307 
308 	    case ',':
309 	      s++;
310 	      goto out;
311 
312 	    case '\\':
313 	      quote_char = '\\';
314 	      break;
315 
316 	    default:
317 	      g_string_append_c (value, *s);
318 	      break;
319 	    }
320 	}
321       else if (quote_char == '\\')
322 	{
323 	  /* \ only counts as an escape if escaping a quote mark */
324 	  if (*s != '\'')
325 	    g_string_append_c (value, '\\');
326 
327 	  g_string_append_c (value, *s);
328 	  quote_char = 0;
329 	}
330       else /* quote_char == ' */
331 	{
332 	  if (*s == '\'')
333 	    quote_char = 0;
334 	  else
335 	    g_string_append_c (value, *s);
336 	}
337     }
338 
339  out:
340 
341   if (quote_char == '\\')
342     g_string_append_c (value, '\\');
343   else if (quote_char == '\'')
344     {
345       g_string_free (value, TRUE);
346       return NULL;
347     }
348 
349   element->value = g_string_free (value, FALSE);
350   return s;
351 }
352 
353 static Match *
match_new(const char * str)354 match_new (const char *str)
355 {
356   Match *match;
357   GArray *elements;
358   const char *p;
359   const char *key_start;
360   const char *key_end;
361   MatchElement element;
362   gboolean eavesdrop;
363   GDBusMessageType type;
364   gsize i;
365 
366   eavesdrop = FALSE;
367   type = G_DBUS_MESSAGE_TYPE_INVALID;
368   elements = g_array_new (TRUE, TRUE, sizeof (MatchElement));
369 
370   p = str;
371 
372   while (*p != 0)
373     {
374       memset (&element, 0, sizeof (element));
375 
376       /* Skip initial whitespace */
377       while (*p && g_ascii_isspace (*p))
378 	p++;
379 
380       key_start = p;
381 
382       /* Read non-whitespace non-equals chars */
383       while (*p && *p != '=' && !g_ascii_isspace (*p))
384 	p++;
385 
386       key_end = p;
387 
388       /* Skip any whitespace after key */
389       while (*p && g_ascii_isspace (*p))
390 	p++;
391 
392       if (key_start == key_end)
393 	continue; /* Allow trailing whitespace */
394 
395       if (*p != '=')
396 	goto error;
397 
398       ++p;
399 
400       if (!parse_key (&element, key_start, key_end))
401 	goto error;
402 
403       p = parse_value (&element, p);
404       if (p == NULL)
405 	goto error;
406 
407       if (element.type == MATCH_ELEMENT_EAVESDROP)
408 	{
409 	  if (strcmp (element.value, "true") == 0)
410 	    eavesdrop = TRUE;
411 	  else if (strcmp (element.value, "false") == 0)
412 	    eavesdrop = FALSE;
413 	  else
414 	    {
415 	      g_free (element.value);
416 	      goto error;
417 	    }
418 	  g_free (element.value);
419 	}
420       else if (element.type == MATCH_ELEMENT_TYPE)
421 	{
422 	  if (strcmp (element.value, "signal") == 0)
423 	    type = G_DBUS_MESSAGE_TYPE_SIGNAL;
424 	  else if (strcmp (element.value, "method_call") == 0)
425 	    type = G_DBUS_MESSAGE_TYPE_METHOD_CALL;
426 	  else if (strcmp (element.value, "method_return") == 0)
427 	    type = G_DBUS_MESSAGE_TYPE_METHOD_RETURN;
428 	  else if (strcmp (element.value, "error") == 0)
429 	    type = G_DBUS_MESSAGE_TYPE_ERROR;
430 	  else
431 	    {
432 	      g_free (element.value);
433 	      goto error;
434 	    }
435 	  g_free (element.value);
436 	}
437       else
438 	g_array_append_val (elements, element);
439     }
440 
441   match = g_new0 (Match, 1);
442   match->n_elements = elements->len;
443   match->elements = (MatchElement *)g_array_free (elements, FALSE);
444   match->eavesdrop = eavesdrop;
445   match->type = type;
446 
447   return match;
448 
449  error:
450   for (i = 0; i < elements->len; i++)
451     g_free (g_array_index (elements, MatchElement, i).value);
452   g_array_free (elements, TRUE);
453   return NULL;
454 }
455 
456 static void
match_free(Match * match)457 match_free (Match *match)
458 {
459   int i;
460   for (i = 0; i < match->n_elements; i++)
461     g_free (match->elements[i].value);
462   g_free (match->elements);
463   g_free (match);
464 }
465 
466 static gboolean
match_equal(Match * a,Match * b)467 match_equal (Match *a, Match *b)
468 {
469   int i;
470 
471   if (a->eavesdrop != b->eavesdrop)
472     return FALSE;
473   if (a->type != b->type)
474     return FALSE;
475  if (a->n_elements != b->n_elements)
476     return FALSE;
477   for (i = 0; i < a->n_elements; i++)
478     {
479       if (a->elements[i].type != b->elements[i].type ||
480 	  a->elements[i].arg != b->elements[i].arg ||
481 	  strcmp (a->elements[i].value, b->elements[i].value) != 0)
482 	return FALSE;
483     }
484   return TRUE;
485 }
486 
487 static const gchar *
message_get_argN(GDBusMessage * message,int n,gboolean allow_path)488 message_get_argN (GDBusMessage *message, int n, gboolean allow_path)
489 {
490   const gchar *ret;
491   GVariant *body;
492 
493   ret = NULL;
494 
495   body = g_dbus_message_get_body (message);
496 
497   if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE_TUPLE))
498     {
499       GVariant *item;
500       item = g_variant_get_child_value (body, n);
501       if (g_variant_is_of_type (item, G_VARIANT_TYPE_STRING) ||
502 	  (allow_path && g_variant_is_of_type (item, G_VARIANT_TYPE_OBJECT_PATH)))
503 	ret = g_variant_get_string (item, NULL);
504       g_variant_unref (item);
505     }
506 
507   return ret;
508 }
509 
510 enum {
511   CHECK_TYPE_STRING,
512   CHECK_TYPE_NAME,
513   CHECK_TYPE_PATH_PREFIX,
514   CHECK_TYPE_PATH_RELATED,
515   CHECK_TYPE_NAMESPACE_PREFIX
516 };
517 
518 static gboolean
match_matches(GDBusDaemon * daemon,Match * match,GDBusMessage * message,gboolean has_destination)519 match_matches (GDBusDaemon *daemon,
520 	       Match *match, GDBusMessage *message,
521 	       gboolean has_destination)
522 {
523   MatchElement *element;
524   Name *name;
525   int i, len, len2;
526   const char *value;
527   int check_type;
528 
529   if (has_destination && !match->eavesdrop)
530     return FALSE;
531 
532   if (match->type != G_DBUS_MESSAGE_TYPE_INVALID &&
533       g_dbus_message_get_message_type (message) != match->type)
534     return FALSE;
535 
536   for (i = 0; i < match->n_elements; i++)
537     {
538       element = &match->elements[i];
539       check_type = CHECK_TYPE_STRING;
540       switch (element->type)
541 	{
542 	case MATCH_ELEMENT_SENDER:
543 	  check_type = CHECK_TYPE_NAME;
544 	  value = g_dbus_message_get_sender (message);
545 	  if (value == NULL)
546 	    value = DBUS_SERVICE_NAME;
547 	  break;
548 	case MATCH_ELEMENT_DESTINATION:
549 	  check_type = CHECK_TYPE_NAME;
550 	  value = g_dbus_message_get_destination (message);
551 	  break;
552 	case MATCH_ELEMENT_INTERFACE:
553 	  value = g_dbus_message_get_interface (message);
554 	  break;
555 	case MATCH_ELEMENT_MEMBER:
556 	  value = g_dbus_message_get_member (message);
557 	  break;
558 	case MATCH_ELEMENT_PATH:
559 	  value = g_dbus_message_get_path (message);
560 	  break;
561 	case MATCH_ELEMENT_PATH_NAMESPACE:
562 	  check_type = CHECK_TYPE_PATH_PREFIX;
563 	  value = g_dbus_message_get_path (message);
564 	  break;
565 	case MATCH_ELEMENT_ARG0NAMESPACE:
566 	  check_type = CHECK_TYPE_NAMESPACE_PREFIX;
567 	  value = message_get_argN (message, 0, FALSE);
568 	  break;
569 	case MATCH_ELEMENT_ARGN:
570 	  value = message_get_argN (message, element->arg, FALSE);
571 	  break;
572 	case MATCH_ELEMENT_ARGNPATH:
573 	  check_type = CHECK_TYPE_PATH_RELATED;
574 	  value = message_get_argN (message, element->arg, TRUE);
575 	  break;
576 	default:
577 	case MATCH_ELEMENT_TYPE:
578 	case MATCH_ELEMENT_EAVESDROP:
579 	  g_assert_not_reached ();
580 	}
581 
582       if (value == NULL)
583 	return FALSE;
584 
585       switch (check_type)
586 	{
587 	case CHECK_TYPE_STRING:
588 	  if (strcmp (element->value, value) != 0)
589 	    return FALSE;
590 	  break;
591 	case CHECK_TYPE_NAME:
592 	  name = name_lookup (daemon, element->value);
593 	  if (name != NULL && name->owner != NULL)
594 	    {
595 	      if (strcmp (name->owner->client->id, value) != 0)
596 		return FALSE;
597 	    }
598 	  else if (strcmp (element->value, value) != 0)
599 	    return FALSE;
600 	  break;
601 	case CHECK_TYPE_PATH_PREFIX:
602 	  len = strlen (element->value);
603 
604 	  /* Make sure to handle the case of element->value == '/'. */
605 	  if (len == 1)
606 	    break;
607 
608 	  /* Fail if there's no prefix match, or if the prefix match doesn't
609 	   * finish at the end of or at a separator in the @value. */
610 	  if (!g_str_has_prefix (value, element->value))
611 	    return FALSE;
612 	  if (value[len] != 0 && value[len] != '/')
613 	    return FALSE;
614 
615 	  break;
616 	case CHECK_TYPE_PATH_RELATED:
617 	  len = strlen (element->value);
618 	  len2 = strlen (value);
619 
620 	  if (!(strcmp (value, element->value) == 0 ||
621 		(len2 > 0 && value[len2-1] == '/' && g_str_has_prefix (element->value, value)) ||
622 		(len > 0 && element->value[len-1] == '/' && g_str_has_prefix (value, element->value))))
623 	    return FALSE;
624 	  break;
625 	case CHECK_TYPE_NAMESPACE_PREFIX:
626 	  len = strlen (element->value);
627 	  if (!(g_str_has_prefix (value, element->value) &&
628 		(value[len] == 0 || value[len] == '.')))
629 	    return FALSE;
630 	  break;
631 	default:
632 	  g_assert_not_reached ();
633 	}
634     }
635 
636   return TRUE;
637 }
638 
639 static void
broadcast_message(GDBusDaemon * daemon,GDBusMessage * message,gboolean has_destination,gboolean preserve_serial,Client * not_to)640 broadcast_message (GDBusDaemon *daemon,
641 		   GDBusMessage *message,
642 		   gboolean has_destination,
643 		   gboolean preserve_serial,
644 		   Client *not_to)
645 {
646   GList *clients, *l, *ll;
647   GDBusMessage *copy;
648 
649   clients = g_hash_table_get_values (daemon->clients);
650   for (l = clients; l != NULL; l = l->next)
651     {
652       Client *client = l->data;
653 
654       if (client == not_to)
655 	continue;
656 
657       for (ll = client->matches; ll != NULL; ll = ll->next)
658 	{
659 	  Match *match = ll->data;
660 
661 	  if (match_matches (daemon, match, message, has_destination))
662 	    break;
663 	}
664 
665       if (ll != NULL)
666 	{
667 	  copy = g_dbus_message_copy (message, NULL);
668 	  if (copy)
669 	    {
670 	      g_dbus_connection_send_message (client->connection, copy,
671 					      preserve_serial?G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL:0, NULL, NULL);
672 	      g_object_unref (copy);
673 	    }
674 	}
675     }
676 
677   g_list_free (clients);
678 }
679 
680 static void
send_name_owner_changed(GDBusDaemon * daemon,const char * name,const char * old_owner,const char * new_owner)681 send_name_owner_changed (GDBusDaemon *daemon,
682 			 const char *name,
683 			 const char *old_owner,
684 			 const char *new_owner)
685 {
686   GDBusMessage *signal_message;
687 
688   signal_message = g_dbus_message_new_signal ("/org/freedesktop/DBus",
689 					      "org.freedesktop.DBus",
690 					      "NameOwnerChanged");
691   g_dbus_message_set_body (signal_message,
692 			   g_variant_new ("(sss)",
693 					  name,
694 					  old_owner ? old_owner : "",
695 					  new_owner ? new_owner : ""));
696 
697   broadcast_message (daemon, signal_message, FALSE, FALSE, NULL);
698   g_object_unref (signal_message);
699 
700 }
701 
702 static gboolean
name_unqueue_owner(Name * name,Client * client)703 name_unqueue_owner (Name *name, Client *client)
704 {
705   GList *l;
706 
707   for (l = name->queue; l != NULL; l = l->next)
708     {
709       NameOwner *other = l->data;
710 
711       if (other->client == client)
712 	{
713 	  name->queue = g_list_delete_link (name->queue, l);
714 	  name_unref (name);
715 	  name_owner_free (other);
716 	  return TRUE;
717 	}
718     }
719 
720   return FALSE;
721 }
722 
723 static void
name_replace_owner(Name * name,NameOwner * owner)724 name_replace_owner (Name *name, NameOwner *owner)
725 {
726   GDBusDaemon *daemon = name->daemon;
727   NameOwner *old_owner;
728   char *old_name = NULL, *new_name = NULL;
729   Client *new_client = NULL;
730 
731   if (owner)
732     new_client = owner->client;
733 
734   name_ref (name);
735 
736   old_owner = name->owner;
737   if (old_owner)
738     {
739       Client *old_client = old_owner->client;
740 
741       g_assert (old_owner->client != new_client);
742 
743       g_dbus_connection_emit_signal (old_client->connection,
744 				     NULL, "/org/freedesktop/DBus",
745 				     "org.freedesktop.DBus", "NameLost",
746 				     g_variant_new ("(s)",
747 						    name->name), NULL);
748 
749       old_name = g_strdup (old_client->id);
750       if (old_owner->flags & DBUS_NAME_FLAG_DO_NOT_QUEUE)
751 	{
752 	  name_unref (name);
753 	  name_owner_free (old_owner);
754 	}
755       else
756 	name->queue = g_list_prepend (name->queue, old_owner);
757     }
758 
759   name->owner = owner;
760   if (owner)
761     {
762       name_unqueue_owner (name, owner->client);
763       name_ref (name);
764       new_name = new_client->id;
765 
766       g_dbus_connection_emit_signal (new_client->connection,
767 				     NULL, "/org/freedesktop/DBus",
768 				     "org.freedesktop.DBus", "NameAcquired",
769 				     g_variant_new ("(s)",
770 						    name->name), NULL);
771     }
772 
773   send_name_owner_changed (daemon, name->name, old_name, new_name);
774 
775   g_free (old_name);
776 
777   name_unref (name);
778 }
779 
780 static void
name_release_owner(Name * name)781 name_release_owner (Name *name)
782 {
783   NameOwner *next_owner = NULL;
784 
785   name_ref (name);
786 
787   /* Will someone else take over? */
788   if (name->queue)
789     {
790       next_owner = name->queue->data;
791       name_unref (name);
792       name->queue = g_list_delete_link (name->queue, name->queue);
793     }
794 
795   name->owner->flags |= DBUS_NAME_FLAG_DO_NOT_QUEUE;
796   name_replace_owner (name, next_owner);
797 
798   name_unref (name);
799 }
800 
801 static void
name_queue_owner(Name * name,NameOwner * owner)802 name_queue_owner (Name *name, NameOwner *owner)
803 {
804   GList *l;
805 
806   for (l = name->queue; l != NULL; l = l->next)
807     {
808       NameOwner *other = l->data;
809 
810       if (other->client == owner->client)
811 	{
812 	  other->flags = owner->flags;
813 	  name_owner_free (owner);
814 	  return;
815 	}
816     }
817 
818   name->queue = g_list_append (name->queue, owner);
819   name_ref (name);
820 }
821 
822 static Client *
client_new(GDBusDaemon * daemon,GDBusConnection * connection)823 client_new (GDBusDaemon *daemon, GDBusConnection *connection)
824 {
825   Client *client;
826   GError *error = NULL;
827 
828   client = g_new0 (Client, 1);
829   client->daemon = daemon;
830   client->id = g_strdup_printf (":%d.%d", daemon->next_major_id, daemon->next_minor_id);
831   client->connection = g_object_ref (connection);
832 
833   if (daemon->next_minor_id == G_MAXUINT32)
834     {
835       daemon->next_minor_id = 0;
836       daemon->next_major_id++;
837     }
838   else
839     daemon->next_minor_id++;
840 
841   g_object_set_data (G_OBJECT (connection), "client", client);
842   g_hash_table_insert (daemon->clients, client->id, client);
843 
844   g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (daemon), connection,
845 				    "/org/freedesktop/DBus", &error);
846   g_assert_no_error (error);
847 
848   g_signal_connect (connection, "closed", G_CALLBACK (connection_closed), client);
849   g_dbus_connection_add_filter (connection,
850 				filter_function,
851 				client, NULL);
852 
853   send_name_owner_changed (daemon, client->id, NULL, client->id);
854 
855   return client;
856 }
857 
858 static void
client_free(Client * client)859 client_free (Client *client)
860 {
861   GDBusDaemon *daemon = client->daemon;
862   GList *l, *names;
863 
864   g_dbus_interface_skeleton_unexport_from_connection (G_DBUS_INTERFACE_SKELETON (daemon),
865 						      client->connection);
866 
867   g_hash_table_remove (daemon->clients, client->id);
868 
869   names = g_hash_table_get_values (daemon->names);
870   for (l = names; l != NULL; l = l->next)
871     {
872       Name *name = l->data;
873 
874       name_ref (name);
875 
876       if (name->owner && name->owner->client == client)
877 	name_release_owner (name);
878 
879       name_unqueue_owner (name, client);
880 
881       name_unref (name);
882     }
883   g_list_free (names);
884 
885   send_name_owner_changed (daemon, client->id, client->id, NULL);
886 
887   g_object_unref (client->connection);
888 
889   for (l = client->matches; l != NULL; l = l->next)
890     match_free (l->data);
891   g_list_free (client->matches);
892 
893   g_free (client->id);
894   g_free (client);
895 }
896 
897 static gboolean
idle_timeout_cb(gpointer user_data)898 idle_timeout_cb (gpointer user_data)
899 {
900   GDBusDaemon *daemon = user_data;
901 
902   daemon->timeout = 0;
903 
904   g_signal_emit (daemon,
905 		 g_dbus_daemon_signals[SIGNAL_IDLE_TIMEOUT],
906 		 0);
907 
908   return G_SOURCE_REMOVE;
909 }
910 
911 static void
connection_closed(GDBusConnection * connection,gboolean remote_peer_vanished,GError * error,Client * client)912 connection_closed (GDBusConnection *connection,
913 		   gboolean remote_peer_vanished,
914 		   GError *error,
915 		   Client *client)
916 {
917   GDBusDaemon *daemon = client->daemon;
918 
919   client_free (client);
920 
921   if (g_hash_table_size (daemon->clients) == 0)
922     daemon->timeout = g_timeout_add (IDLE_TIMEOUT_MSEC,
923 				     idle_timeout_cb,
924 				     daemon);
925 }
926 
927 static gboolean
handle_add_match(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_rule)928 handle_add_match (_GFreedesktopDBus *object,
929 		  GDBusMethodInvocation *invocation,
930 		  const gchar *arg_rule)
931 {
932   Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
933   Match *match;
934 
935   match = match_new (arg_rule);
936 
937   if (match == NULL)
938     g_dbus_method_invocation_return_error (invocation,
939 					   G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_INVALID,
940 					   "Invalid rule: %s", arg_rule);
941   else
942     {
943       client->matches = g_list_prepend (client->matches, match);
944       _g_freedesktop_dbus_complete_add_match (object, invocation);
945     }
946   return TRUE;
947 }
948 
949 static gboolean
handle_get_connection_selinux_security_context(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name)950 handle_get_connection_selinux_security_context (_GFreedesktopDBus *object,
951 						GDBusMethodInvocation *invocation,
952 						const gchar *arg_name)
953 {
954   g_dbus_method_invocation_return_error (invocation,
955 					 G_DBUS_ERROR, G_DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN,
956 					 "selinux context not supported");
957   _g_freedesktop_dbus_complete_get_connection_selinux_security_context (object, invocation, "");
958   return TRUE;
959 }
960 
961 static gboolean
handle_get_connection_unix_process_id(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name)962 handle_get_connection_unix_process_id (_GFreedesktopDBus *object,
963 				       GDBusMethodInvocation *invocation,
964 				       const gchar *arg_name)
965 {
966   g_dbus_method_invocation_return_error (invocation,
967 					 G_DBUS_ERROR, G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
968 					 "connection pid not supported");
969   return TRUE;
970 }
971 
972 static gboolean
handle_get_connection_unix_user(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name)973 handle_get_connection_unix_user (_GFreedesktopDBus *object,
974 				 GDBusMethodInvocation *invocation,
975 				 const gchar *arg_name)
976 {
977   g_dbus_method_invocation_return_error (invocation,
978 					 G_DBUS_ERROR, G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
979 					 "connection user not supported");
980   return TRUE;
981 }
982 
983 static gboolean
handle_get_id(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation)984 handle_get_id (_GFreedesktopDBus *object,
985 	       GDBusMethodInvocation *invocation)
986 {
987   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
988   _g_freedesktop_dbus_complete_get_id (object, invocation,
989 				       daemon->guid);
990   return TRUE;
991 }
992 
993 static gboolean
handle_get_name_owner(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name)994 handle_get_name_owner (_GFreedesktopDBus *object,
995 		       GDBusMethodInvocation *invocation,
996 		       const gchar *arg_name)
997 {
998   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
999   Name *name;
1000 
1001   if (strcmp (arg_name, DBUS_SERVICE_NAME) == 0)
1002     {
1003       _g_freedesktop_dbus_complete_get_name_owner (object, invocation, DBUS_SERVICE_NAME);
1004       return TRUE;
1005     }
1006 
1007   if (arg_name[0] == ':')
1008     {
1009       if (g_hash_table_lookup (daemon->clients, arg_name) == NULL)
1010 	g_dbus_method_invocation_return_error (invocation,
1011 					       G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
1012 					       "Could not get owner of name '%s': no such name", arg_name);
1013       else
1014 	_g_freedesktop_dbus_complete_get_name_owner (object, invocation, arg_name);
1015       return TRUE;
1016     }
1017 
1018   name = name_lookup (daemon, arg_name);
1019   if (name == NULL || name->owner == NULL)
1020     {
1021       g_dbus_method_invocation_return_error (invocation,
1022 					     G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
1023 					     "Could not get owner of name '%s': no such name", arg_name);
1024       return TRUE;
1025     }
1026 
1027   _g_freedesktop_dbus_complete_get_name_owner (object, invocation, name->owner->client->id);
1028   return TRUE;
1029 }
1030 
1031 static gboolean
handle_hello(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation)1032 handle_hello (_GFreedesktopDBus *object,
1033 	      GDBusMethodInvocation *invocation)
1034 {
1035   Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
1036   _g_freedesktop_dbus_complete_hello (object, invocation, client->id);
1037 
1038   g_dbus_connection_emit_signal (client->connection,
1039 				 NULL, "/org/freedesktop/DBus",
1040 				 "org.freedesktop.DBus", "NameAcquired",
1041 				 g_variant_new ("(s)",
1042 						client->id), NULL);
1043 
1044   return TRUE;
1045 }
1046 
1047 static gboolean
handle_list_activatable_names(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation)1048 handle_list_activatable_names (_GFreedesktopDBus *object,
1049 			       GDBusMethodInvocation *invocation)
1050 {
1051   const char *names[] = { NULL };
1052 
1053   _g_freedesktop_dbus_complete_list_activatable_names (object,
1054 						       invocation,
1055 						       names);
1056   return TRUE;
1057 }
1058 
1059 static gboolean
handle_list_names(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation)1060 handle_list_names (_GFreedesktopDBus *object,
1061 		   GDBusMethodInvocation *invocation)
1062 {
1063   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1064   GPtrArray *array;
1065   GList *clients, *names, *l;
1066 
1067   array = g_ptr_array_new ();
1068 
1069   clients = g_hash_table_get_values (daemon->clients);
1070   for (l = clients; l != NULL; l = l->next)
1071     {
1072       Client *client = l->data;
1073 
1074       g_ptr_array_add (array, client->id);
1075     }
1076 
1077   g_list_free (clients);
1078 
1079   names = g_hash_table_get_values (daemon->names);
1080   for (l = names; l != NULL; l = l->next)
1081     {
1082       Name *name = l->data;
1083 
1084       g_ptr_array_add (array, name->name);
1085     }
1086 
1087   g_list_free (names);
1088 
1089   g_ptr_array_add (array, NULL);
1090 
1091   _g_freedesktop_dbus_complete_list_names (object,
1092 					   invocation,
1093 					   (const gchar * const*)array->pdata);
1094   g_ptr_array_free (array, TRUE);
1095   return TRUE;
1096 }
1097 
1098 static gboolean
handle_list_queued_owners(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name)1099 handle_list_queued_owners (_GFreedesktopDBus *object,
1100 			   GDBusMethodInvocation *invocation,
1101 			   const gchar *arg_name)
1102 {
1103   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1104   GPtrArray *array;
1105   Name *name;
1106   GList *l;
1107 
1108   array = g_ptr_array_new ();
1109 
1110   name = name_lookup (daemon, arg_name);
1111   if (name && name->owner)
1112     {
1113       for (l = name->queue; l != NULL; l = l->next)
1114 	{
1115 	  Client *client = l->data;
1116 
1117 	  g_ptr_array_add (array, client->id);
1118 	}
1119     }
1120 
1121   g_ptr_array_add (array, NULL);
1122 
1123   _g_freedesktop_dbus_complete_list_queued_owners (object,
1124 						   invocation,
1125 						   (const gchar * const*)array->pdata);
1126   g_ptr_array_free (array, TRUE);
1127   return TRUE;
1128 }
1129 
1130 static gboolean
handle_name_has_owner(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name)1131 handle_name_has_owner (_GFreedesktopDBus *object,
1132 		       GDBusMethodInvocation *invocation,
1133 		       const gchar *arg_name)
1134 {
1135   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1136   Name *name;
1137   Client *client;
1138 
1139   name = name_lookup (daemon, arg_name);
1140   client = g_hash_table_lookup (daemon->clients, arg_name);
1141 
1142   _g_freedesktop_dbus_complete_name_has_owner (object, invocation,
1143 					       name != NULL || client != NULL);
1144   return TRUE;
1145 }
1146 
1147 static gboolean
handle_release_name(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name)1148 handle_release_name (_GFreedesktopDBus *object,
1149 		     GDBusMethodInvocation *invocation,
1150 		     const gchar *arg_name)
1151 {
1152   Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
1153   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1154   Name *name;
1155   guint32 result;
1156 
1157   if (!g_dbus_is_name (arg_name))
1158     {
1159       g_dbus_method_invocation_return_error (invocation,
1160 					     G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
1161 					     "Given bus name \"%s\" is not valid", arg_name);
1162       return TRUE;
1163     }
1164 
1165   if (*arg_name == ':')
1166     {
1167       g_dbus_method_invocation_return_error (invocation,
1168 					     G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
1169 					     "Cannot release a service starting with ':' such as \"%s\"", arg_name);
1170       return TRUE;
1171     }
1172 
1173   if (strcmp (arg_name, DBUS_SERVICE_NAME) == 0)
1174     {
1175       g_dbus_method_invocation_return_error (invocation,
1176 					     G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
1177 					     "Cannot release a service named " DBUS_SERVICE_NAME ", because that is owned by the bus");
1178       return TRUE;
1179     }
1180 
1181   name = name_lookup (daemon, arg_name);
1182 
1183   if (name == NULL)
1184     result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
1185   else if (name->owner && name->owner->client == client)
1186     {
1187       name_release_owner (name);
1188       result = DBUS_RELEASE_NAME_REPLY_RELEASED;
1189     }
1190   else if (name_unqueue_owner (name, client))
1191     result = DBUS_RELEASE_NAME_REPLY_RELEASED;
1192   else
1193     result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
1194 
1195   _g_freedesktop_dbus_complete_release_name (object, invocation, result);
1196   return TRUE;
1197 }
1198 
1199 static gboolean
handle_reload_config(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation)1200 handle_reload_config (_GFreedesktopDBus *object,
1201 		      GDBusMethodInvocation *invocation)
1202 {
1203   _g_freedesktop_dbus_complete_reload_config (object, invocation);
1204   return TRUE;
1205 }
1206 
1207 static gboolean
handle_update_activation_environment(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,GVariant * arg_environment)1208 handle_update_activation_environment (_GFreedesktopDBus *object,
1209 				      GDBusMethodInvocation *invocation,
1210 				      GVariant *arg_environment)
1211 {
1212   g_dbus_method_invocation_return_error (invocation,
1213 					 G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1214 					 "UpdateActivationEnvironment not implemented");
1215   return TRUE;
1216 }
1217 
1218 static gboolean
handle_remove_match(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_rule)1219 handle_remove_match (_GFreedesktopDBus *object,
1220 		     GDBusMethodInvocation *invocation,
1221 		     const gchar *arg_rule)
1222 {
1223   Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
1224   Match *match, *other_match;
1225   GList *l;
1226 
1227   match = match_new (arg_rule);
1228 
1229   if (match == NULL)
1230     g_dbus_method_invocation_return_error (invocation,
1231 					   G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_INVALID,
1232 					   "Invalid rule: %s", arg_rule);
1233   else
1234     {
1235       for (l = client->matches; l != NULL; l = l->next)
1236 	{
1237 	  other_match = l->data;
1238 	  if (match_equal (match, other_match))
1239 	    {
1240 	      match_free (other_match);
1241 	      client->matches = g_list_delete_link (client->matches, l);
1242 	      break;
1243 	    }
1244 	}
1245 
1246       if (l == NULL)
1247 	g_dbus_method_invocation_return_error (invocation,
1248 					       G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_NOT_FOUND,
1249 					       "The given match rule wasn't found and can't be removed");
1250       else
1251 	_g_freedesktop_dbus_complete_remove_match (object, invocation);
1252     }
1253   if (match)
1254     match_free (match);
1255 
1256   return TRUE;
1257 }
1258 
1259 static gboolean
handle_request_name(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name,guint flags)1260 handle_request_name (_GFreedesktopDBus *object,
1261 		     GDBusMethodInvocation *invocation,
1262 		     const gchar *arg_name,
1263 		     guint flags)
1264 {
1265   Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
1266   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1267   Name *name;
1268   NameOwner *owner;
1269   guint32 result;
1270 
1271   if (!g_dbus_is_name (arg_name))
1272     {
1273       g_dbus_method_invocation_return_error (invocation,
1274 					     G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
1275 					     "Requested bus name \"%s\" is not valid", arg_name);
1276       return TRUE;
1277     }
1278 
1279   if (*arg_name == ':')
1280     {
1281       g_dbus_method_invocation_return_error (invocation,
1282 					     G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
1283 					     "Cannot acquire a service starting with ':' such as \"%s\"", arg_name);
1284       return TRUE;
1285     }
1286 
1287   if (strcmp (arg_name, DBUS_SERVICE_NAME) == 0)
1288     {
1289       g_dbus_method_invocation_return_error (invocation,
1290 					     G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
1291 					     "Cannot acquire a service named " DBUS_SERVICE_NAME ", because that is reserved");
1292       return TRUE;
1293     }
1294 
1295   name = name_ensure (daemon, arg_name);
1296   if (name->owner == NULL)
1297     {
1298       owner = name_owner_new (client, flags);
1299       name_replace_owner (name, owner);
1300 
1301       result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
1302     }
1303   else if (name->owner && name->owner->client == client)
1304     {
1305       name->owner->flags = flags;
1306       result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
1307     }
1308   else if ((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
1309 	   (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
1310 	    !(name->owner->flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT)))
1311     {
1312       /* Unqueue if queued */
1313       name_unqueue_owner (name, client);
1314       result = DBUS_REQUEST_NAME_REPLY_EXISTS;
1315     }
1316   else if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
1317 	   (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
1318 	    !(name->owner->flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT)))
1319     {
1320       /* Queue the connection */
1321       owner = name_owner_new (client, flags);
1322       name_queue_owner (name, owner);
1323       result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
1324     }
1325   else
1326     {
1327       /* Replace the current owner */
1328 
1329       owner = name_owner_new (client, flags);
1330       name_replace_owner (name, owner);
1331 
1332       result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
1333     }
1334 
1335   name_unref (name);
1336 
1337   _g_freedesktop_dbus_complete_request_name (object, invocation, result);
1338   return TRUE;
1339 }
1340 
1341 static gboolean
handle_start_service_by_name(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name,guint arg_flags)1342 handle_start_service_by_name (_GFreedesktopDBus *object,
1343 			      GDBusMethodInvocation *invocation,
1344 			      const gchar *arg_name,
1345 			      guint arg_flags)
1346 {
1347   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1348   Name *name;
1349 
1350   name = name_lookup (daemon, arg_name);
1351   if (name)
1352     _g_freedesktop_dbus_complete_start_service_by_name (object, invocation,
1353 							DBUS_START_REPLY_ALREADY_RUNNING);
1354   else
1355     g_dbus_method_invocation_return_error (invocation,
1356 					   G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN,
1357 					   "No support for activation for name: %s", arg_name);
1358 
1359   return TRUE;
1360 }
1361 
1362 G_GNUC_PRINTF(5, 6)
1363 static void
return_error(Client * client,GDBusMessage * message,GQuark domain,gint code,const gchar * format,...)1364 return_error (Client *client, GDBusMessage *message,
1365 	      GQuark                 domain,
1366 	      gint                   code,
1367 	      const gchar           *format,
1368 	      ...)
1369 {
1370   GDBusMessage *reply;
1371   va_list var_args;
1372   char *error_message;
1373   GError *error;
1374   gchar *dbus_error_name;
1375 
1376   va_start (var_args, format);
1377   error_message = g_strdup_vprintf (format, var_args);
1378   va_end (var_args);
1379 
1380   error = g_error_new_literal (domain, code, "");
1381   dbus_error_name = g_dbus_error_encode_gerror (error);
1382 
1383   reply = g_dbus_message_new_method_error_literal (message,
1384 						   dbus_error_name,
1385 						   error_message);
1386 
1387   g_error_free (error);
1388   g_free (dbus_error_name);
1389   g_free (error_message);
1390 
1391   if (!g_dbus_connection_send_message (client->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL))
1392       g_warning ("Error sending reply");
1393   g_object_unref (reply);
1394 }
1395 
1396 static GDBusMessage *
route_message(Client * source_client,GDBusMessage * message)1397 route_message (Client *source_client, GDBusMessage *message)
1398 {
1399   const char *dest;
1400   Client *dest_client;
1401   GDBusDaemon *daemon;
1402 
1403   daemon = source_client->daemon;
1404 
1405   dest_client = NULL;
1406   dest = g_dbus_message_get_destination (message);
1407   if (dest != NULL && strcmp (dest, DBUS_SERVICE_NAME) != 0)
1408     {
1409       dest_client = g_hash_table_lookup (daemon->clients, dest);
1410 
1411       if (dest_client == NULL)
1412 	{
1413 	  Name *name;
1414 	  name = name_lookup (daemon, dest);
1415 	  if (name && name->owner)
1416 	    dest_client = name->owner->client;
1417 	}
1418 
1419       if (dest_client == NULL)
1420 	{
1421 	  if (g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL)
1422 	    return_error (source_client, message,
1423 			  G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN,
1424 			  "The name %s is unknown", dest);
1425 	}
1426       else
1427 	{
1428 	  GError *error = NULL;
1429 
1430 	  if (!g_dbus_connection_send_message (dest_client->connection, message, G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL, NULL, &error))
1431 	    {
1432 	      g_warning ("Error forwarding message: %s", error->message);
1433 	      g_error_free (error);
1434 	    }
1435 	}
1436     }
1437 
1438   broadcast_message (daemon, message, dest_client != NULL, TRUE, dest_client);
1439 
1440   /* Swallow messages not for the bus */
1441   if (dest == NULL || strcmp (dest, DBUS_SERVICE_NAME) != 0)
1442     {
1443       g_object_unref (message);
1444       message = NULL;
1445     }
1446 
1447   return message;
1448 }
1449 
1450 static GDBusMessage *
copy_if_locked(GDBusMessage * message)1451 copy_if_locked (GDBusMessage *message)
1452 {
1453   if (g_dbus_message_get_locked (message))
1454     {
1455       GDBusMessage *copy = g_dbus_message_copy (message, NULL);
1456       g_object_unref (message);
1457       message = copy;
1458     }
1459   return message;
1460 }
1461 
1462 static GDBusMessage *
filter_function(GDBusConnection * connection,GDBusMessage * message,gboolean incoming,gpointer user_data)1463 filter_function (GDBusConnection *connection,
1464 		 GDBusMessage    *message,
1465 		 gboolean         incoming,
1466 		 gpointer         user_data)
1467 {
1468   Client *client = user_data;
1469 
1470   if (0)
1471     {
1472       const char *types[] = {"invalid", "method_call", "method_return", "error", "signal" };
1473       g_printerr ("%s%s %s %d(%d) sender: %s destination: %s %s %s.%s\n",
1474 		client->id,
1475 		incoming? "->" : "<-",
1476 		types[g_dbus_message_get_message_type (message)],
1477 		g_dbus_message_get_serial (message),
1478 		g_dbus_message_get_reply_serial (message),
1479 		g_dbus_message_get_sender (message),
1480 		g_dbus_message_get_destination (message),
1481 		g_dbus_message_get_path (message),
1482 		g_dbus_message_get_interface (message),
1483 		g_dbus_message_get_member (message));
1484     }
1485 
1486   if (incoming)
1487     {
1488       /* Ensure its not locked so we can set the sender */
1489       message = copy_if_locked (message);
1490       if (message == NULL)
1491 	{
1492 	  g_warning ("Failed to copy incoming message");
1493 	  return NULL;
1494 	}
1495       g_dbus_message_set_sender (message, client->id);
1496 
1497       return route_message (client, message);
1498     }
1499   else
1500     {
1501       if (g_dbus_message_get_sender (message) == NULL ||
1502           g_dbus_message_get_destination (message) == NULL)
1503         {
1504           message = copy_if_locked (message);
1505           if (message == NULL)
1506             {
1507               g_warning ("Failed to copy outgoing message");
1508               return NULL;
1509             }
1510         }
1511 
1512       if (g_dbus_message_get_sender (message) == NULL)
1513         g_dbus_message_set_sender (message, DBUS_SERVICE_NAME);
1514       if (g_dbus_message_get_destination (message) == NULL)
1515         g_dbus_message_set_destination (message, client->id);
1516     }
1517 
1518   return message;
1519 }
1520 
1521 static gboolean
on_new_connection(GDBusServer * server,GDBusConnection * connection,gpointer user_data)1522 on_new_connection (GDBusServer *server,
1523 		   GDBusConnection *connection,
1524 		   gpointer user_data)
1525 {
1526   GDBusDaemon *daemon = user_data;
1527 
1528   g_dbus_connection_set_exit_on_close (connection, FALSE);
1529 
1530   if (daemon->timeout)
1531     {
1532       g_source_remove (daemon->timeout);
1533       daemon->timeout = 0;
1534     }
1535 
1536   client_new (daemon, connection);
1537 
1538   return TRUE;
1539 }
1540 
1541 static void
g_dbus_daemon_finalize(GObject * object)1542 g_dbus_daemon_finalize (GObject *object)
1543 {
1544   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1545   GList *clients, *l;
1546 
1547   if (daemon->timeout)
1548     g_source_remove (daemon->timeout);
1549 
1550   clients = g_hash_table_get_values (daemon->clients);
1551   for (l = clients; l != NULL; l = l->next)
1552     client_free (l->data);
1553   g_list_free (clients);
1554 
1555   g_assert (g_hash_table_size (daemon->clients) == 0);
1556   g_assert (g_hash_table_size (daemon->names) == 0);
1557 
1558   g_hash_table_destroy (daemon->clients);
1559   g_hash_table_destroy (daemon->names);
1560 
1561   g_object_unref (daemon->server);
1562 
1563   if (daemon->tmpdir)
1564     {
1565       g_rmdir (daemon->tmpdir);
1566       g_free (daemon->tmpdir);
1567     }
1568 
1569   g_free (daemon->guid);
1570   g_free (daemon->address);
1571 
1572   G_OBJECT_CLASS (g_dbus_daemon_parent_class)->finalize (object);
1573 }
1574 
1575 static void
g_dbus_daemon_init(GDBusDaemon * daemon)1576 g_dbus_daemon_init (GDBusDaemon *daemon)
1577 {
1578   daemon->next_major_id = 1;
1579   daemon->clients = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
1580   daemon->names = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
1581   daemon->guid = g_dbus_generate_guid ();
1582 }
1583 
1584 static gboolean
initable_init(GInitable * initable,GCancellable * cancellable,GError ** error)1585 initable_init (GInitable     *initable,
1586 	       GCancellable  *cancellable,
1587 	       GError       **error)
1588 {
1589   GDBusDaemon *daemon = G_DBUS_DAEMON (initable);
1590   GDBusServerFlags flags;
1591 
1592   flags = G_DBUS_SERVER_FLAGS_NONE;
1593   if (daemon->address == NULL)
1594     {
1595 #ifdef G_OS_UNIX
1596       if (g_unix_socket_address_abstract_names_supported ())
1597 	daemon->address = g_strdup ("unix:tmpdir=/tmp/gdbus-daemon");
1598       else
1599 	{
1600 	  daemon->tmpdir = g_dir_make_tmp ("gdbus-daemon-XXXXXX", NULL);
1601 	  daemon->address = g_strdup_printf ("unix:tmpdir=%s", daemon->tmpdir);
1602 	}
1603       flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER;
1604 #else
1605       /* Don’t require authentication on Windows as that hasn’t been
1606        * implemented yet. */
1607       daemon->address = g_strdup ("nonce-tcp:");
1608       flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS;
1609 #endif
1610     }
1611 
1612   daemon->server = g_dbus_server_new_sync (daemon->address,
1613 					   flags,
1614 					   daemon->guid,
1615 					   NULL,
1616 					   cancellable,
1617 					   error);
1618   if (daemon->server == NULL)
1619     return FALSE;
1620 
1621 
1622   g_dbus_server_start (daemon->server);
1623 
1624   g_signal_connect (daemon->server, "new-connection",
1625 		    G_CALLBACK (on_new_connection),
1626 		    daemon);
1627 
1628   return TRUE;
1629 }
1630 
1631 static void
g_dbus_daemon_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1632 g_dbus_daemon_set_property (GObject      *object,
1633 			    guint         prop_id,
1634 			    const GValue *value,
1635 			    GParamSpec   *pspec)
1636 {
1637   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1638 
1639   switch (prop_id)
1640     {
1641     case PROP_ADDRESS:
1642       g_free (daemon->address);
1643       daemon->address = g_value_dup_string (value);
1644       break;
1645 
1646     default:
1647       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1648     }
1649 }
1650 
1651 static void
g_dbus_daemon_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1652 g_dbus_daemon_get_property (GObject    *object,
1653 			    guint       prop_id,
1654 			    GValue     *value,
1655 			    GParamSpec *pspec)
1656 {
1657   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1658 
1659   switch (prop_id)
1660     {
1661       case PROP_ADDRESS:
1662 	g_value_set_string (value, daemon->address);
1663 	break;
1664 
1665     default:
1666 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1667     }
1668 }
1669 
1670 static void
g_dbus_daemon_class_init(GDBusDaemonClass * klass)1671 g_dbus_daemon_class_init (GDBusDaemonClass *klass)
1672 {
1673   GObjectClass *gobject_class;
1674 
1675   gobject_class = G_OBJECT_CLASS (klass);
1676   gobject_class->finalize = g_dbus_daemon_finalize;
1677   gobject_class->set_property = g_dbus_daemon_set_property;
1678   gobject_class->get_property = g_dbus_daemon_get_property;
1679 
1680   g_dbus_daemon_signals[SIGNAL_IDLE_TIMEOUT] =
1681     g_signal_new (I_("idle-timeout"),
1682 		  G_TYPE_DBUS_DAEMON,
1683 		  G_SIGNAL_RUN_LAST,
1684 		  0,
1685 		  NULL, NULL,
1686 		  NULL,
1687 		  G_TYPE_NONE, 0);
1688 
1689   g_object_class_install_property (gobject_class,
1690 				   PROP_ADDRESS,
1691 				   g_param_spec_string ("address",
1692 							"Bus Address",
1693 							"The address the bus should use",
1694 							NULL,
1695 							G_PARAM_READWRITE |
1696 							G_PARAM_CONSTRUCT_ONLY |
1697 							G_PARAM_STATIC_STRINGS));
1698 }
1699 
1700 static void
g_dbus_daemon_iface_init(_GFreedesktopDBusIface * iface)1701 g_dbus_daemon_iface_init (_GFreedesktopDBusIface *iface)
1702 {
1703   iface->handle_add_match = handle_add_match;
1704   iface->handle_get_connection_selinux_security_context = handle_get_connection_selinux_security_context;
1705   iface->handle_get_connection_unix_process_id = handle_get_connection_unix_process_id;
1706   iface->handle_get_connection_unix_user = handle_get_connection_unix_user;
1707   iface->handle_get_id = handle_get_id;
1708   iface->handle_get_name_owner = handle_get_name_owner;
1709   iface->handle_hello = handle_hello;
1710   iface->handle_list_activatable_names = handle_list_activatable_names;
1711   iface->handle_list_names = handle_list_names;
1712   iface->handle_list_queued_owners = handle_list_queued_owners;
1713   iface->handle_name_has_owner = handle_name_has_owner;
1714   iface->handle_release_name = handle_release_name;
1715   iface->handle_reload_config = handle_reload_config;
1716   iface->handle_update_activation_environment = handle_update_activation_environment;
1717   iface->handle_remove_match = handle_remove_match;
1718   iface->handle_request_name = handle_request_name;
1719   iface->handle_start_service_by_name = handle_start_service_by_name;
1720 }
1721 
1722 static void
initable_iface_init(GInitableIface * initable_iface)1723 initable_iface_init (GInitableIface *initable_iface)
1724 {
1725   initable_iface->init = initable_init;
1726 }
1727 
1728 GDBusDaemon *
_g_dbus_daemon_new(const char * address,GCancellable * cancellable,GError ** error)1729 _g_dbus_daemon_new (const char *address,
1730 		    GCancellable *cancellable,
1731 		    GError **error)
1732 {
1733   return g_initable_new (G_TYPE_DBUS_DAEMON,
1734 			 cancellable,
1735 			 error,
1736 			 "address", address,
1737 			 NULL);
1738 }
1739 
1740 const char *
_g_dbus_daemon_get_address(GDBusDaemon * daemon)1741 _g_dbus_daemon_get_address (GDBusDaemon *daemon)
1742 {
1743   return g_dbus_server_get_client_address (daemon->server);
1744 }
1745