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