1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dispatch.c  Message dispatcher
3  *
4  * Copyright (C) 2003  CodeFactory AB
5  * Copyright (C) 2003, 2004, 2005  Red Hat, Inc.
6  * Copyright (C) 2004  Imendio HB
7  *
8  * Licensed under the Academic Free License version 2.1
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23  *
24  */
25 
26 #include <config.h>
27 #include "dispatch.h"
28 #include "connection.h"
29 #include "driver.h"
30 #include "services.h"
31 #include "activation.h"
32 #include "utils.h"
33 #include "bus.h"
34 #include "signals.h"
35 #include "test.h"
36 #include <dbus/dbus-internals.h>
37 #include <dbus/dbus-misc.h>
38 #include <string.h>
39 
40 #ifdef HAVE_UNIX_FD_PASSING
41 #include <dbus/dbus-sysdeps-unix.h>
42 #include <unistd.h>
43 #endif
44 
45 /* This is hard-coded in the files in valid-config-files-*. We have to use
46  * the debug-pipe transport because the tests in this file require that
47  * dbus_connection_open_private() does not block. */
48 #define TEST_DEBUG_PIPE "debug-pipe:name=test-server"
49 
50 static inline const char *
nonnull(const char * maybe_null,const char * if_null)51 nonnull (const char *maybe_null,
52          const char *if_null)
53 {
54   return (maybe_null ? maybe_null : if_null);
55 }
56 
57 static dbus_bool_t
send_one_message(DBusConnection * connection,BusContext * context,DBusConnection * sender,DBusConnection * addressed_recipient,DBusMessage * message,BusTransaction * transaction,DBusError * error)58 send_one_message (DBusConnection *connection,
59                   BusContext     *context,
60                   DBusConnection *sender,
61                   DBusConnection *addressed_recipient,
62                   DBusMessage    *message,
63                   BusTransaction *transaction,
64                   DBusError      *error)
65 {
66   DBusError stack_error = DBUS_ERROR_INIT;
67 
68   if (!bus_context_check_security_policy (context, transaction,
69                                           sender,
70                                           addressed_recipient,
71                                           connection,
72                                           message,
73                                           NULL,
74                                           &stack_error))
75     {
76       if (!bus_transaction_capture_error_reply (transaction, sender,
77                                                 &stack_error, message))
78         {
79           bus_context_log (context, DBUS_SYSTEM_LOG_WARNING,
80                            "broadcast rejected, but not enough "
81                            "memory to tell monitors");
82         }
83 
84       dbus_error_free (&stack_error);
85       return TRUE; /* don't send it but don't return an error either */
86     }
87 
88   if (dbus_message_contains_unix_fds(message) &&
89       !dbus_connection_can_send_type(connection, DBUS_TYPE_UNIX_FD))
90     {
91       dbus_set_error (&stack_error, DBUS_ERROR_NOT_SUPPORTED,
92                       "broadcast cannot be delivered to %s (%s) because "
93                       "it does not support receiving Unix fds",
94                       bus_connection_get_name (connection),
95                       bus_connection_get_loginfo (connection));
96 
97       if (!bus_transaction_capture_error_reply (transaction, sender,
98                                                 &stack_error, message))
99         {
100           bus_context_log (context, DBUS_SYSTEM_LOG_WARNING,
101                            "broadcast with Unix fd not delivered, but not "
102                            "enough memory to tell monitors");
103         }
104 
105       dbus_error_free (&stack_error);
106       return TRUE; /* don't send it but don't return an error either */
107     }
108 
109   if (!bus_transaction_send (transaction,
110                              connection,
111                              message))
112     {
113       BUS_SET_OOM (error);
114       return FALSE;
115     }
116 
117   return TRUE;
118 }
119 
120 dbus_bool_t
bus_dispatch_matches(BusTransaction * transaction,DBusConnection * sender,DBusConnection * addressed_recipient,DBusMessage * message,DBusError * error)121 bus_dispatch_matches (BusTransaction *transaction,
122                       DBusConnection *sender,
123                       DBusConnection *addressed_recipient,
124                       DBusMessage    *message,
125                       DBusError      *error)
126 {
127   DBusError tmp_error;
128   BusConnections *connections;
129   DBusList *recipients;
130   BusMatchmaker *matchmaker;
131   DBusList *link;
132   BusContext *context;
133 
134   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
135 
136   /* sender and recipient can both be NULL for the bus driver,
137    * or for signals with no particular recipient
138    */
139 
140   _dbus_assert (sender == NULL || bus_connection_is_active (sender));
141   _dbus_assert (dbus_message_get_sender (message) != NULL);
142 
143   context = bus_transaction_get_context (transaction);
144 
145   /* First, send the message to the addressed_recipient, if there is one. */
146   if (addressed_recipient != NULL)
147     {
148       if (!bus_context_check_security_policy (context, transaction,
149                                               sender, addressed_recipient,
150                                               addressed_recipient,
151                                               message, NULL, error))
152         return FALSE;
153 
154       if (dbus_message_contains_unix_fds (message) &&
155           !dbus_connection_can_send_type (addressed_recipient,
156                                           DBUS_TYPE_UNIX_FD))
157         {
158           dbus_set_error (error,
159                           DBUS_ERROR_NOT_SUPPORTED,
160                           "Tried to send message with Unix file descriptors"
161                           "to a client that doesn't support that.");
162           return FALSE;
163       }
164 
165       /* Dispatch the message */
166       if (!bus_transaction_send (transaction, addressed_recipient, message))
167         {
168           BUS_SET_OOM (error);
169           return FALSE;
170         }
171     }
172 
173   /* Now dispatch to others who look interested in this message */
174   connections = bus_context_get_connections (context);
175   dbus_error_init (&tmp_error);
176   matchmaker = bus_context_get_matchmaker (context);
177 
178   recipients = NULL;
179   if (!bus_matchmaker_get_recipients (matchmaker, connections,
180                                       sender, addressed_recipient, message,
181                                       &recipients))
182     {
183       BUS_SET_OOM (error);
184       return FALSE;
185     }
186 
187   link = _dbus_list_get_first_link (&recipients);
188   while (link != NULL)
189     {
190       DBusConnection *dest;
191 
192       dest = link->data;
193 
194       if (!send_one_message (dest, context, sender, addressed_recipient,
195                              message, transaction, &tmp_error))
196         break;
197 
198       link = _dbus_list_get_next_link (&recipients, link);
199     }
200 
201   _dbus_list_clear (&recipients);
202 
203   if (dbus_error_is_set (&tmp_error))
204     {
205       dbus_move_error (&tmp_error, error);
206       return FALSE;
207     }
208   else
209     return TRUE;
210 }
211 
212 static DBusHandlerResult
bus_dispatch(DBusConnection * connection,DBusMessage * message)213 bus_dispatch (DBusConnection *connection,
214               DBusMessage    *message)
215 {
216   const char *sender, *service_name;
217   DBusError error;
218   BusTransaction *transaction;
219   BusContext *context;
220   DBusHandlerResult result;
221   DBusConnection *addressed_recipient;
222 
223   result = DBUS_HANDLER_RESULT_HANDLED;
224 
225   transaction = NULL;
226   addressed_recipient = NULL;
227   dbus_error_init (&error);
228 
229   context = bus_connection_get_context (connection);
230   _dbus_assert (context != NULL);
231 
232   /* If we can't even allocate an OOM error, we just go to sleep
233    * until we can.
234    */
235   while (!bus_connection_preallocate_oom_error (connection))
236     _dbus_wait_for_memory ();
237 
238   /* Ref connection in case we disconnect it at some point in here */
239   dbus_connection_ref (connection);
240 
241   /* Monitors aren't meant to send messages to us. */
242   if (bus_connection_is_monitor (connection))
243     {
244       sender = bus_connection_get_name (connection);
245 
246       /* should never happen */
247       if (sender == NULL)
248         sender = "(unknown)";
249 
250       if (dbus_message_is_signal (message,
251                                   DBUS_INTERFACE_LOCAL,
252                                   "Disconnected"))
253         {
254           bus_context_log (context, DBUS_SYSTEM_LOG_INFO,
255                            "Monitoring connection %s closed.", sender);
256           bus_connection_disconnected (connection);
257           goto out;
258         }
259       else
260         {
261           /* Monitors are not allowed to send messages, because that
262            * probably indicates that the monitor is incorrectly replying
263            * to its eavesdropped messages, and we want the authors of
264            * such monitors to fix them.
265            */
266           bus_context_log (context, DBUS_SYSTEM_LOG_WARNING,
267                            "Monitoring connection %s (%s) is not allowed "
268                            "to send messages; closing it. Please fix the "
269                            "monitor to not do that. "
270                            "(message type=\"%s\" interface=\"%s\" "
271                            "member=\"%s\" error name=\"%s\" "
272                            "destination=\"%s\")",
273                            sender, bus_connection_get_loginfo (connection),
274                            dbus_message_type_to_string (
275                              dbus_message_get_type (message)),
276                            nonnull (dbus_message_get_interface (message),
277                                     "(unset)"),
278                            nonnull (dbus_message_get_member (message),
279                                     "(unset)"),
280                            nonnull (dbus_message_get_error_name (message),
281                                     "(unset)"),
282                            nonnull (dbus_message_get_destination (message),
283                                     DBUS_SERVICE_DBUS));
284           dbus_connection_close (connection);
285           goto out;
286         }
287     }
288 
289   service_name = dbus_message_get_destination (message);
290 
291 #ifdef DBUS_ENABLE_VERBOSE_MODE
292   {
293     const char *interface_name, *member_name, *error_name;
294 
295     interface_name = dbus_message_get_interface (message);
296     member_name = dbus_message_get_member (message);
297     error_name = dbus_message_get_error_name (message);
298 
299     _dbus_verbose ("DISPATCH: %s %s %s to %s\n",
300                    interface_name ? interface_name : "(no interface)",
301                    member_name ? member_name : "(no member)",
302                    error_name ? error_name : "(no error name)",
303                    service_name ? service_name : "peer");
304   }
305 #endif /* DBUS_ENABLE_VERBOSE_MODE */
306 
307   /* If service_name is NULL, if it's a signal we send it to all
308    * connections with a match rule. If it's not a signal, there
309    * are some special cases here but mostly we just bail out.
310    */
311   if (service_name == NULL)
312     {
313       if (dbus_message_is_signal (message,
314                                   DBUS_INTERFACE_LOCAL,
315                                   "Disconnected"))
316         {
317           bus_connection_disconnected (connection);
318           goto out;
319         }
320 
321       if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL)
322         {
323           /* DBusConnection also handles some of these automatically, we leave
324            * it to do so.
325            *
326            * FIXME: this means monitors won't get the opportunity to see
327            * non-signals with NULL destination, or their replies (which in
328            * practice are UnknownMethod errors)
329            */
330           result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
331           goto out;
332         }
333     }
334 
335   /* Create our transaction */
336   transaction = bus_transaction_new (context);
337   if (transaction == NULL)
338     {
339       BUS_SET_OOM (&error);
340       goto out;
341     }
342 
343   /* Assign a sender to the message */
344   if (bus_connection_is_active (connection))
345     {
346       sender = bus_connection_get_name (connection);
347       _dbus_assert (sender != NULL);
348 
349       if (!dbus_message_set_sender (message, sender))
350         {
351           BUS_SET_OOM (&error);
352           goto out;
353         }
354     }
355   else
356     {
357       /* For monitors' benefit: we don't want the sender to be able to
358        * trick the monitor by supplying a forged sender, and we also
359        * don't want the message to have no sender at all. */
360       if (!dbus_message_set_sender (message, ":not.active.yet"))
361         {
362           BUS_SET_OOM (&error);
363           goto out;
364         }
365     }
366 
367   /* We need to refetch the service name here, because
368    * dbus_message_set_sender can cause the header to be
369    * reallocated, and thus the service_name pointer will become
370    * invalid.
371    */
372   service_name = dbus_message_get_destination (message);
373 
374   if (service_name &&
375       strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */
376     {
377       if (!bus_transaction_capture (transaction, connection, NULL, message))
378         {
379           BUS_SET_OOM (&error);
380           goto out;
381         }
382 
383       if (!bus_context_check_security_policy (context, transaction,
384                                               connection, NULL, NULL, message,
385                                               NULL, &error))
386         {
387           _dbus_verbose ("Security policy rejected message\n");
388           goto out;
389         }
390 
391       _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_DBUS);
392       if (!bus_driver_handle_message (connection, transaction, message, &error))
393         goto out;
394     }
395   else if (!bus_connection_is_active (connection)) /* clients must talk to bus driver first */
396     {
397       if (!bus_transaction_capture (transaction, connection, NULL, message))
398         {
399           BUS_SET_OOM (&error);
400           goto out;
401         }
402 
403       _dbus_verbose ("Received message from non-registered client. Disconnecting.\n");
404       dbus_connection_close (connection);
405       goto out;
406     }
407   else if (service_name != NULL) /* route to named service */
408     {
409       DBusString service_string;
410       BusService *service;
411       BusRegistry *registry;
412 
413       _dbus_assert (service_name != NULL);
414 
415       registry = bus_connection_get_registry (connection);
416 
417       _dbus_string_init_const (&service_string, service_name);
418       service = bus_registry_lookup (registry, &service_string);
419 
420       if (service == NULL && dbus_message_get_auto_start (message))
421         {
422           BusActivation *activation;
423 
424           if (!bus_transaction_capture (transaction, connection, NULL,
425                                         message))
426             {
427               BUS_SET_OOM (&error);
428               goto out;
429             }
430 
431           activation = bus_connection_get_activation (connection);
432 
433           /* This will do as much of a security policy check as it can.
434            * We can't do the full security policy check here, since the
435            * addressed recipient service doesn't exist yet. We do it before
436            * sending the message after the service has been created.
437            */
438           if (!bus_activation_activate_service (activation, connection, transaction, TRUE,
439                                                 message, service_name, &error))
440             {
441               _DBUS_ASSERT_ERROR_IS_SET (&error);
442               _dbus_verbose ("bus_activation_activate_service() failed: %s\n", error.name);
443               goto out;
444             }
445 
446           goto out;
447         }
448       else if (service == NULL)
449         {
450           if (!bus_transaction_capture (transaction, connection,
451                                         NULL, message))
452             {
453               BUS_SET_OOM (&error);
454               goto out;
455             }
456 
457           dbus_set_error (&error,
458                           DBUS_ERROR_NAME_HAS_NO_OWNER,
459                           "Name \"%s\" does not exist",
460                           service_name);
461           goto out;
462         }
463       else
464         {
465           addressed_recipient = bus_service_get_primary_owners_connection (service);
466           _dbus_assert (addressed_recipient != NULL);
467 
468           if (!bus_transaction_capture (transaction, connection,
469                                         addressed_recipient, message))
470             {
471               BUS_SET_OOM (&error);
472               goto out;
473             }
474         }
475     }
476   else /* service_name == NULL */
477     {
478       if (!bus_transaction_capture (transaction, connection, NULL, message))
479         {
480           BUS_SET_OOM (&error);
481           goto out;
482         }
483     }
484 
485   /* Now send the message to its destination (or not, if
486    * addressed_recipient == NULL), and match it against other connections'
487    * match rules.
488    */
489   if (!bus_dispatch_matches (transaction, connection, addressed_recipient, message, &error))
490     goto out;
491 
492  out:
493   if (dbus_error_is_set (&error))
494     {
495       /* Even if we disconnected it, pretend to send it any pending error
496        * messages so that monitors can observe them.
497        */
498       if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
499         {
500           bus_connection_send_oom_error (connection, message);
501 
502           /* cancel transaction due to OOM */
503           if (transaction != NULL)
504             {
505               bus_transaction_cancel_and_free (transaction);
506               transaction = NULL;
507             }
508         }
509       else
510         {
511           /* Try to send the real error, if no mem to do that, send
512            * the OOM error
513            */
514           _dbus_assert (transaction != NULL);
515           if (!bus_transaction_send_error_reply (transaction, connection,
516                                                  &error, message))
517             {
518               bus_connection_send_oom_error (connection, message);
519 
520               /* cancel transaction due to OOM */
521               if (transaction != NULL)
522                 {
523                   bus_transaction_cancel_and_free (transaction);
524                   transaction = NULL;
525                 }
526             }
527         }
528 
529 
530       dbus_error_free (&error);
531     }
532 
533   if (transaction != NULL)
534     {
535       bus_transaction_execute_and_free (transaction);
536     }
537 
538   dbus_connection_unref (connection);
539 
540   return result;
541 }
542 
543 static DBusHandlerResult
bus_dispatch_message_filter(DBusConnection * connection,DBusMessage * message,void * user_data)544 bus_dispatch_message_filter (DBusConnection     *connection,
545                              DBusMessage        *message,
546                              void               *user_data)
547 {
548   return bus_dispatch (connection, message);
549 }
550 
551 dbus_bool_t
bus_dispatch_add_connection(DBusConnection * connection)552 bus_dispatch_add_connection (DBusConnection *connection)
553 {
554   if (!dbus_connection_add_filter (connection,
555                                    bus_dispatch_message_filter,
556                                    NULL, NULL))
557     return FALSE;
558 
559   return TRUE;
560 }
561 
562 void
bus_dispatch_remove_connection(DBusConnection * connection)563 bus_dispatch_remove_connection (DBusConnection *connection)
564 {
565   /* Here we tell the bus driver that we want to get off. */
566   bus_driver_remove_connection (connection);
567 
568   dbus_connection_remove_filter (connection,
569                                  bus_dispatch_message_filter,
570                                  NULL);
571 }
572 
573 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
574 
575 #include <stdio.h>
576 
577 #include "stats.h"
578 
579 /* This is used to know whether we need to block in order to finish
580  * sending a message, or whether the initial dbus_connection_send()
581  * already flushed the queue.
582  */
583 #define SEND_PENDING(connection) (dbus_connection_has_messages_to_send (connection))
584 
585 typedef dbus_bool_t (* Check1Func) (BusContext     *context);
586 typedef dbus_bool_t (* Check2Func) (BusContext     *context,
587                                     DBusConnection *connection);
588 
589 static dbus_bool_t check_no_leftovers (BusContext *context);
590 
591 static void
block_connection_until_message_from_bus(BusContext * context,DBusConnection * connection,const char * what_is_expected)592 block_connection_until_message_from_bus (BusContext     *context,
593                                          DBusConnection *connection,
594                                          const char     *what_is_expected)
595 {
596   _dbus_verbose ("expecting: %s\n", what_is_expected);
597 
598   while (dbus_connection_get_dispatch_status (connection) ==
599          DBUS_DISPATCH_COMPLETE &&
600          dbus_connection_get_is_connected (connection))
601     {
602       bus_test_run_bus_loop (context, TRUE);
603       bus_test_run_clients_loop (FALSE);
604     }
605 }
606 
607 static void
spin_connection_until_authenticated(BusContext * context,DBusConnection * connection)608 spin_connection_until_authenticated (BusContext     *context,
609                                      DBusConnection *connection)
610 {
611   _dbus_verbose ("Spinning to auth connection %p\n", connection);
612   while (!dbus_connection_get_is_authenticated (connection) &&
613          dbus_connection_get_is_connected (connection))
614     {
615       bus_test_run_bus_loop (context, FALSE);
616       bus_test_run_clients_loop (FALSE);
617     }
618   _dbus_verbose (" ... done spinning to auth connection %p\n", connection);
619 }
620 
621 /* compensate for fact that pop_message() can return #NULL due to OOM */
622 static DBusMessage*
pop_message_waiting_for_memory(DBusConnection * connection)623 pop_message_waiting_for_memory (DBusConnection *connection)
624 {
625   while (dbus_connection_get_dispatch_status (connection) ==
626          DBUS_DISPATCH_NEED_MEMORY)
627     _dbus_wait_for_memory ();
628 
629   return dbus_connection_pop_message (connection);
630 }
631 
632 static DBusMessage*
borrow_message_waiting_for_memory(DBusConnection * connection)633 borrow_message_waiting_for_memory (DBusConnection *connection)
634 {
635   while (dbus_connection_get_dispatch_status (connection) ==
636          DBUS_DISPATCH_NEED_MEMORY)
637     _dbus_wait_for_memory ();
638 
639   return dbus_connection_borrow_message (connection);
640 }
641 
642 static void
warn_unexpected_real(DBusConnection * connection,DBusMessage * message,const char * expected,const char * function,int line)643 warn_unexpected_real (DBusConnection *connection,
644                       DBusMessage    *message,
645                       const char     *expected,
646                       const char     *function,
647                       int             line)
648 {
649   if (message)
650     _dbus_warn ("%s:%d received message interface \"%s\" member \"%s\" error name \"%s\" on %p, expecting %s",
651                 function, line,
652                 dbus_message_get_interface (message) ?
653                 dbus_message_get_interface (message) : "(unset)",
654                 dbus_message_get_member (message) ?
655                 dbus_message_get_member (message) : "(unset)",
656                 dbus_message_get_error_name (message) ?
657                 dbus_message_get_error_name (message) : "(unset)",
658                 connection,
659                 expected);
660   else
661     _dbus_warn ("%s:%d received no message on %p, expecting %s",
662                 function, line, connection, expected);
663 }
664 
665 #define warn_unexpected(connection, message, expected) \
666   warn_unexpected_real (connection, message, expected, _DBUS_FUNCTION_NAME, __LINE__)
667 
668 static void
verbose_message_received(DBusConnection * connection,DBusMessage * message)669 verbose_message_received (DBusConnection *connection,
670                           DBusMessage    *message)
671 {
672   _dbus_verbose ("Received message interface \"%s\" member \"%s\" error name \"%s\" on %p\n",
673                  dbus_message_get_interface (message) ?
674                  dbus_message_get_interface (message) : "(unset)",
675                  dbus_message_get_member (message) ?
676                  dbus_message_get_member (message) : "(unset)",
677                  dbus_message_get_error_name (message) ?
678                  dbus_message_get_error_name (message) : "(unset)",
679                  connection);
680 }
681 
682 typedef enum
683 {
684   SERVICE_CREATED,
685   OWNER_CHANGED,
686   SERVICE_DELETED
687 } ServiceInfoKind;
688 
689 typedef struct
690 {
691   ServiceInfoKind expected_kind;
692   const char *expected_service_name;
693   dbus_bool_t failed;
694   DBusConnection *skip_connection;
695   BusContext *context;
696 } CheckServiceOwnerChangedData;
697 
698 static dbus_bool_t
check_service_owner_changed_foreach(DBusConnection * connection,void * data)699 check_service_owner_changed_foreach (DBusConnection *connection,
700                                      void           *data)
701 {
702   CheckServiceOwnerChangedData *d = data;
703   DBusMessage *message;
704   DBusError error;
705   const char *service_name, *old_owner, *new_owner;
706 
707   if (d->expected_kind == SERVICE_CREATED
708       && connection == d->skip_connection)
709     return TRUE;
710 
711   dbus_error_init (&error);
712   d->failed = TRUE;
713 
714   message = pop_message_waiting_for_memory (connection);
715   if (message == NULL)
716     {
717       block_connection_until_message_from_bus (d->context, connection, "NameOwnerChanged");
718       message = pop_message_waiting_for_memory (connection);
719       if (message == NULL)
720         {
721           _dbus_warn ("Did not receive a message on %p, expecting %s",
722                       connection, "NameOwnerChanged");
723           goto out;
724         }
725     }
726   else if (!dbus_message_is_signal (message,
727                                     DBUS_INTERFACE_DBUS,
728                                     "NameOwnerChanged"))
729     {
730       warn_unexpected (connection, message, "NameOwnerChanged");
731 
732       goto out;
733     }
734   else
735     {
736     reget_service_info_data:
737       service_name = NULL;
738       old_owner = NULL;
739       new_owner = NULL;
740 
741       dbus_message_get_args (message, &error,
742                              DBUS_TYPE_STRING, &service_name,
743                              DBUS_TYPE_STRING, &old_owner,
744                              DBUS_TYPE_STRING, &new_owner,
745                              DBUS_TYPE_INVALID);
746 
747       if (dbus_error_is_set (&error))
748         {
749           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
750             {
751               dbus_error_free (&error);
752               _dbus_wait_for_memory ();
753               goto reget_service_info_data;
754             }
755           else
756             {
757               _dbus_warn ("Did not get the expected arguments");
758               goto out;
759             }
760         }
761 
762       if ((d->expected_kind == SERVICE_CREATED    && ( old_owner[0] || !new_owner[0]))
763           || (d->expected_kind == OWNER_CHANGED   && (!old_owner[0] || !new_owner[0]))
764           || (d->expected_kind == SERVICE_DELETED && (!old_owner[0] ||  new_owner[0])))
765         {
766           _dbus_warn ("inconsistent NameOwnerChanged arguments");
767           goto out;
768         }
769 
770       if (strcmp (service_name, d->expected_service_name) != 0)
771         {
772           _dbus_warn ("expected info on service %s, got info on %s",
773                       d->expected_service_name,
774                       service_name);
775           goto out;
776         }
777 
778       if (*service_name == ':' && new_owner[0]
779           && strcmp (service_name, new_owner) != 0)
780         {
781           _dbus_warn ("inconsistent ServiceOwnedChanged message (\"%s\" [ %s -> %s ])",
782                       service_name, old_owner, new_owner);
783           goto out;
784         }
785     }
786 
787   d->failed = FALSE;
788 
789  out:
790   dbus_error_free (&error);
791 
792   if (message)
793     dbus_message_unref (message);
794 
795   return !d->failed;
796 }
797 
798 
799 static void
kill_client_connection(BusContext * context,DBusConnection * connection)800 kill_client_connection (BusContext     *context,
801                         DBusConnection *connection)
802 {
803   char *base_service;
804   const char *s;
805   CheckServiceOwnerChangedData socd;
806 
807   _dbus_verbose ("killing connection %p\n", connection);
808 
809   s = dbus_bus_get_unique_name (connection);
810   _dbus_assert (s != NULL);
811 
812   while ((base_service = _dbus_strdup (s)) == NULL)
813     _dbus_wait_for_memory ();
814 
815   dbus_connection_ref (connection);
816 
817   /* kick in the disconnect handler that unrefs the connection */
818   dbus_connection_close (connection);
819 
820   bus_test_run_everything (context);
821 
822   _dbus_assert (bus_test_client_listed (connection));
823 
824   /* Run disconnect handler in test.c */
825   if (bus_connection_dispatch_one_message (connection))
826     _dbus_assert_not_reached ("something received on connection being killed other than the disconnect");
827 
828   _dbus_assert (!dbus_connection_get_is_connected (connection));
829   dbus_connection_unref (connection);
830   connection = NULL;
831   _dbus_assert (!bus_test_client_listed (connection));
832 
833   socd.expected_kind = SERVICE_DELETED;
834   socd.expected_service_name = base_service;
835   socd.failed = FALSE;
836   socd.skip_connection = NULL;
837   socd.context = context;
838 
839   bus_test_clients_foreach (check_service_owner_changed_foreach,
840                             &socd);
841 
842   dbus_free (base_service);
843 
844   if (socd.failed)
845     _dbus_assert_not_reached ("didn't get the expected NameOwnerChanged (deletion) messages");
846 
847   if (!check_no_leftovers (context))
848     _dbus_assert_not_reached ("stuff left in message queues after disconnecting a client");
849 }
850 
851 static void
kill_client_connection_unchecked(DBusConnection * connection)852 kill_client_connection_unchecked (DBusConnection *connection)
853 {
854   /* This kills the connection without expecting it to affect
855    * the rest of the bus.
856    */
857   _dbus_verbose ("Unchecked kill of connection %p\n", connection);
858 
859   dbus_connection_ref (connection);
860   dbus_connection_close (connection);
861   /* dispatching disconnect handler will unref once */
862   if (bus_connection_dispatch_one_message (connection))
863     _dbus_assert_not_reached ("message other than disconnect dispatched after failure to register");
864 
865   _dbus_assert (!bus_test_client_listed (connection));
866   dbus_connection_unref (connection);
867 }
868 
869 typedef struct
870 {
871   dbus_bool_t failed;
872 } CheckNoMessagesData;
873 
874 static dbus_bool_t
check_no_messages_foreach(DBusConnection * connection,void * data)875 check_no_messages_foreach (DBusConnection *connection,
876                            void           *data)
877 {
878   CheckNoMessagesData *d = data;
879   DBusMessage *message;
880 
881   message = pop_message_waiting_for_memory (connection);
882   if (message != NULL)
883     {
884       warn_unexpected (connection, message, "no messages");
885 
886       d->failed = TRUE;
887     }
888 
889   if (message)
890     dbus_message_unref (message);
891   return !d->failed;
892 }
893 
894 static dbus_bool_t
check_no_leftovers(BusContext * context)895 check_no_leftovers (BusContext *context)
896 {
897   CheckNoMessagesData nmd;
898 
899   nmd.failed = FALSE;
900   bus_test_clients_foreach (check_no_messages_foreach,
901                             &nmd);
902 
903   if (nmd.failed)
904     {
905       _dbus_verbose ("leftover message found\n");
906       return FALSE;
907     }
908   else
909     return TRUE;
910 }
911 
912 /* returns TRUE if the correct thing happens,
913  * but the correct thing may include OOM errors.
914  */
915 static dbus_bool_t
check_hello_message(BusContext * context,DBusConnection * connection)916 check_hello_message (BusContext     *context,
917                      DBusConnection *connection)
918 {
919   DBusMessage *message;
920   DBusMessage *name_message;
921   dbus_uint32_t serial;
922   dbus_bool_t retval;
923   DBusError error;
924   const char *name;
925   const char *acquired;
926 
927   retval = FALSE;
928   dbus_error_init (&error);
929   name = NULL;
930   acquired = NULL;
931   message = NULL;
932   name_message = NULL;
933 
934   _dbus_verbose ("check_hello_message for %p\n", connection);
935 
936   message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
937                                           DBUS_PATH_DBUS,
938                                           DBUS_INTERFACE_DBUS,
939                                           "Hello");
940 
941   if (message == NULL)
942     return TRUE;
943 
944   dbus_connection_ref (connection); /* because we may get disconnected */
945 
946   if (!dbus_connection_send (connection, message, &serial))
947     {
948       dbus_message_unref (message);
949       dbus_connection_unref (connection);
950       return TRUE;
951     }
952 
953   _dbus_assert (dbus_message_has_signature (message, ""));
954 
955   dbus_message_unref (message);
956   message = NULL;
957 
958   if (!dbus_connection_get_is_connected (connection))
959     {
960       _dbus_verbose ("connection was disconnected (presumably auth failed)\n");
961 
962       dbus_connection_unref (connection);
963 
964       return TRUE;
965     }
966 
967   /* send our message */
968   bus_test_run_clients_loop (SEND_PENDING (connection));
969 
970   if (!dbus_connection_get_is_connected (connection))
971     {
972       _dbus_verbose ("connection was disconnected (presumably auth failed)\n");
973 
974       dbus_connection_unref (connection);
975 
976       return TRUE;
977     }
978 
979   block_connection_until_message_from_bus (context, connection, "reply to Hello");
980 
981   if (!dbus_connection_get_is_connected (connection))
982     {
983       _dbus_verbose ("connection was disconnected (presumably auth failed)\n");
984 
985       dbus_connection_unref (connection);
986 
987       return TRUE;
988     }
989 
990   message = pop_message_waiting_for_memory (connection);
991   if (message == NULL)
992     {
993       _dbus_warn ("Did not receive a reply to %s %d on %p",
994                   "Hello", serial, connection);
995       goto out;
996     }
997 
998   verbose_message_received (connection, message);
999 
1000   if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
1001     {
1002       _dbus_warn ("Message has wrong sender %s",
1003                   dbus_message_get_sender (message) ?
1004                   dbus_message_get_sender (message) : "(none)");
1005       goto out;
1006     }
1007 
1008   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1009     {
1010       if (dbus_message_is_error (message,
1011                                  DBUS_ERROR_NO_MEMORY))
1012         {
1013           ; /* good, this is a valid response */
1014         }
1015       else
1016         {
1017           warn_unexpected (connection, message, "not this error");
1018 
1019           goto out;
1020         }
1021     }
1022   else
1023     {
1024       CheckServiceOwnerChangedData socd;
1025 
1026       if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1027         {
1028           ; /* good, expected */
1029         }
1030       else
1031         {
1032           warn_unexpected (connection, message, "method return for Hello");
1033 
1034           goto out;
1035         }
1036 
1037     retry_get_hello_name:
1038       if (!dbus_message_get_args (message, &error,
1039                                   DBUS_TYPE_STRING, &name,
1040                                   DBUS_TYPE_INVALID))
1041         {
1042           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1043             {
1044               _dbus_verbose ("no memory to get service name arg from hello\n");
1045               dbus_error_free (&error);
1046               _dbus_wait_for_memory ();
1047               goto retry_get_hello_name;
1048             }
1049           else
1050             {
1051               _dbus_assert (dbus_error_is_set (&error));
1052               _dbus_warn ("Did not get the expected single string argument to hello");
1053               goto out;
1054             }
1055         }
1056 
1057       _dbus_verbose ("Got hello name: %s\n", name);
1058 
1059       while (!dbus_bus_set_unique_name (connection, name))
1060         _dbus_wait_for_memory ();
1061 
1062       socd.expected_kind = SERVICE_CREATED;
1063       socd.expected_service_name = name;
1064       socd.failed = FALSE;
1065       socd.skip_connection = connection; /* we haven't done AddMatch so won't get it ourselves */
1066       socd.context = context;
1067 
1068       bus_test_clients_foreach (check_service_owner_changed_foreach,
1069                                 &socd);
1070 
1071       if (socd.failed)
1072         goto out;
1073 
1074       name_message = message;
1075       /* Client should also have gotten ServiceAcquired */
1076 
1077       message = pop_message_waiting_for_memory (connection);
1078       if (message == NULL)
1079         {
1080           block_connection_until_message_from_bus (context, connection, "signal NameAcquired");
1081           message = pop_message_waiting_for_memory (connection);
1082           if (message == NULL)
1083             {
1084               _dbus_warn ("Expecting %s, got nothing",
1085                       "NameAcquired");
1086               goto out;
1087             }
1088         }
1089       if (! dbus_message_is_signal (message, DBUS_INTERFACE_DBUS,
1090                                     "NameAcquired"))
1091         {
1092           _dbus_warn ("Expecting %s, got smthg else",
1093                       "NameAcquired");
1094           goto out;
1095         }
1096 
1097     retry_get_acquired_name:
1098       if (!dbus_message_get_args (message, &error,
1099                                   DBUS_TYPE_STRING, &acquired,
1100                                   DBUS_TYPE_INVALID))
1101         {
1102           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1103             {
1104               _dbus_verbose ("no memory to get service name arg from acquired\n");
1105               dbus_error_free (&error);
1106               _dbus_wait_for_memory ();
1107               goto retry_get_acquired_name;
1108             }
1109           else
1110             {
1111               _dbus_assert (dbus_error_is_set (&error));
1112               _dbus_warn ("Did not get the expected single string argument to ServiceAcquired");
1113               goto out;
1114             }
1115         }
1116 
1117       _dbus_verbose ("Got acquired name: %s\n", acquired);
1118 
1119       if (strcmp (acquired, name) != 0)
1120         {
1121           _dbus_warn ("Acquired name is %s but expected %s",
1122                       acquired, name);
1123           goto out;
1124         }
1125       acquired = NULL;
1126     }
1127 
1128   if (!check_no_leftovers (context))
1129     goto out;
1130 
1131   retval = TRUE;
1132 
1133  out:
1134   _dbus_verbose ("ending - retval = %d\n", retval);
1135 
1136   dbus_error_free (&error);
1137 
1138   if (message)
1139     dbus_message_unref (message);
1140 
1141   if (name_message)
1142     dbus_message_unref (name_message);
1143 
1144   dbus_connection_unref (connection);
1145 
1146   return retval;
1147 }
1148 
1149 /* returns TRUE if the correct thing happens,
1150  * but the correct thing may include OOM errors.
1151  */
1152 static dbus_bool_t
check_double_hello_message(BusContext * context,DBusConnection * connection)1153 check_double_hello_message (BusContext     *context,
1154                             DBusConnection *connection)
1155 {
1156   DBusMessage *message;
1157   dbus_uint32_t serial;
1158   dbus_bool_t retval;
1159   DBusError error;
1160 
1161   retval = FALSE;
1162   dbus_error_init (&error);
1163   message = NULL;
1164 
1165   _dbus_verbose ("check_double_hello_message for %p\n", connection);
1166 
1167   message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1168                                           DBUS_PATH_DBUS,
1169                                           DBUS_INTERFACE_DBUS,
1170                                           "Hello");
1171 
1172   if (message == NULL)
1173     return TRUE;
1174 
1175   if (!dbus_connection_send (connection, message, &serial))
1176     {
1177       dbus_message_unref (message);
1178       return TRUE;
1179     }
1180 
1181   dbus_message_unref (message);
1182   message = NULL;
1183 
1184   /* send our message */
1185   bus_test_run_clients_loop (SEND_PENDING (connection));
1186 
1187   dbus_connection_ref (connection); /* because we may get disconnected */
1188   block_connection_until_message_from_bus (context, connection, "reply to Hello");
1189 
1190   if (!dbus_connection_get_is_connected (connection))
1191     {
1192       _dbus_verbose ("connection was disconnected\n");
1193 
1194       dbus_connection_unref (connection);
1195 
1196       return TRUE;
1197     }
1198 
1199   dbus_connection_unref (connection);
1200 
1201   message = pop_message_waiting_for_memory (connection);
1202   if (message == NULL)
1203     {
1204       _dbus_warn ("Did not receive a reply to %s %d on %p",
1205                   "Hello", serial, connection);
1206       goto out;
1207     }
1208 
1209   verbose_message_received (connection, message);
1210 
1211   if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
1212     {
1213       _dbus_warn ("Message has wrong sender %s",
1214                   dbus_message_get_sender (message) ?
1215                   dbus_message_get_sender (message) : "(none)");
1216       goto out;
1217     }
1218 
1219   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
1220     {
1221       warn_unexpected (connection, message, "method return for Hello");
1222       goto out;
1223     }
1224 
1225   if (!check_no_leftovers (context))
1226     goto out;
1227 
1228   retval = TRUE;
1229 
1230  out:
1231   dbus_error_free (&error);
1232 
1233   if (message)
1234     dbus_message_unref (message);
1235 
1236   return retval;
1237 }
1238 
1239 /* returns TRUE if the correct thing happens,
1240  * but the correct thing may include OOM errors.
1241  */
1242 static dbus_bool_t
check_get_connection_unix_user(BusContext * context,DBusConnection * connection)1243 check_get_connection_unix_user (BusContext     *context,
1244                                 DBusConnection *connection)
1245 {
1246   DBusMessage *message;
1247   dbus_uint32_t serial;
1248   dbus_bool_t retval;
1249   DBusError error;
1250   const char *base_service_name;
1251   dbus_uint32_t uid;
1252 
1253   retval = FALSE;
1254   dbus_error_init (&error);
1255   message = NULL;
1256 
1257   _dbus_verbose ("check_get_connection_unix_user for %p\n", connection);
1258 
1259   message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1260                                           DBUS_PATH_DBUS,
1261                                           DBUS_INTERFACE_DBUS,
1262                                           "GetConnectionUnixUser");
1263 
1264   if (message == NULL)
1265     return TRUE;
1266 
1267   base_service_name = dbus_bus_get_unique_name (connection);
1268 
1269   if (!dbus_message_append_args (message,
1270                                  DBUS_TYPE_STRING, &base_service_name,
1271                                  DBUS_TYPE_INVALID))
1272     {
1273       dbus_message_unref (message);
1274       return TRUE;
1275     }
1276 
1277   if (!dbus_connection_send (connection, message, &serial))
1278     {
1279       dbus_message_unref (message);
1280       return TRUE;
1281     }
1282 
1283   /* send our message */
1284   bus_test_run_clients_loop (SEND_PENDING (connection));
1285 
1286   dbus_message_unref (message);
1287   message = NULL;
1288 
1289   dbus_connection_ref (connection); /* because we may get disconnected */
1290   block_connection_until_message_from_bus (context, connection, "reply to GetConnectionUnixUser");
1291 
1292   if (!dbus_connection_get_is_connected (connection))
1293     {
1294       _dbus_verbose ("connection was disconnected\n");
1295 
1296       dbus_connection_unref (connection);
1297 
1298       return TRUE;
1299     }
1300 
1301   dbus_connection_unref (connection);
1302 
1303   message = pop_message_waiting_for_memory (connection);
1304   if (message == NULL)
1305     {
1306       _dbus_warn ("Did not receive a reply to %s %d on %p",
1307                   "GetConnectionUnixUser", serial, connection);
1308       goto out;
1309     }
1310 
1311   verbose_message_received (connection, message);
1312 
1313   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1314     {
1315       if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY))
1316         {
1317           ; /* good, this is a valid response */
1318         }
1319 #ifdef DBUS_WIN
1320       else if (dbus_message_is_error (message, DBUS_ERROR_FAILED))
1321         {
1322           /* this is OK, Unix uids aren't meaningful on Windows */
1323         }
1324 #endif
1325       else
1326         {
1327           warn_unexpected (connection, message, "not this error");
1328 
1329           goto out;
1330         }
1331     }
1332   else
1333     {
1334       if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1335         {
1336           ; /* good, expected */
1337         }
1338       else
1339         {
1340           warn_unexpected (connection, message,
1341                            "method_return for GetConnectionUnixUser");
1342 
1343           goto out;
1344         }
1345 
1346     retry_get_property:
1347 
1348       if (!dbus_message_get_args (message, &error,
1349                                   DBUS_TYPE_UINT32, &uid,
1350                                   DBUS_TYPE_INVALID))
1351         {
1352           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1353             {
1354               _dbus_verbose ("no memory to get uid by GetConnectionUnixUser\n");
1355               dbus_error_free (&error);
1356               _dbus_wait_for_memory ();
1357               goto retry_get_property;
1358             }
1359           else
1360             {
1361               _dbus_assert (dbus_error_is_set (&error));
1362               _dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetConnectionUnixUser");
1363               goto out;
1364             }
1365         }
1366     }
1367 
1368   if (!check_no_leftovers (context))
1369     goto out;
1370 
1371   retval = TRUE;
1372 
1373  out:
1374   dbus_error_free (&error);
1375 
1376   if (message)
1377     dbus_message_unref (message);
1378 
1379   return retval;
1380 }
1381 
1382 /* returns TRUE if the correct thing happens,
1383  * but the correct thing may include OOM errors.
1384  */
1385 static dbus_bool_t
check_get_connection_unix_process_id(BusContext * context,DBusConnection * connection)1386 check_get_connection_unix_process_id (BusContext     *context,
1387                                       DBusConnection *connection)
1388 {
1389   DBusMessage *message;
1390   dbus_uint32_t serial;
1391   dbus_bool_t retval;
1392   DBusError error;
1393   const char *base_service_name;
1394 #ifdef DBUS_UNIX
1395   dbus_uint32_t pid;
1396 #endif
1397 
1398   retval = FALSE;
1399   dbus_error_init (&error);
1400   message = NULL;
1401 
1402   _dbus_verbose ("check_get_connection_unix_process_id for %p\n", connection);
1403 
1404   message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1405                                           DBUS_PATH_DBUS,
1406                                           DBUS_INTERFACE_DBUS,
1407                                           "GetConnectionUnixProcessID");
1408 
1409   if (message == NULL)
1410     return TRUE;
1411 
1412   base_service_name = dbus_bus_get_unique_name (connection);
1413 
1414   if (!dbus_message_append_args (message,
1415                                  DBUS_TYPE_STRING, &base_service_name,
1416                                  DBUS_TYPE_INVALID))
1417     {
1418       dbus_message_unref (message);
1419       return TRUE;
1420     }
1421 
1422   if (!dbus_connection_send (connection, message, &serial))
1423     {
1424       dbus_message_unref (message);
1425       return TRUE;
1426     }
1427 
1428   /* send our message */
1429   bus_test_run_clients_loop (SEND_PENDING (connection));
1430 
1431   dbus_message_unref (message);
1432   message = NULL;
1433 
1434   dbus_connection_ref (connection); /* because we may get disconnected */
1435   block_connection_until_message_from_bus (context, connection, "reply to GetConnectionUnixProcessID");
1436 
1437   if (!dbus_connection_get_is_connected (connection))
1438     {
1439       _dbus_verbose ("connection was disconnected\n");
1440 
1441       dbus_connection_unref (connection);
1442 
1443       return TRUE;
1444     }
1445 
1446   dbus_connection_unref (connection);
1447 
1448   message = pop_message_waiting_for_memory (connection);
1449   if (message == NULL)
1450     {
1451       _dbus_warn ("Did not receive a reply to %s %d on %p",
1452                   "GetConnectionUnixProcessID", serial, connection);
1453       goto out;
1454     }
1455 
1456   verbose_message_received (connection, message);
1457 
1458   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1459     {
1460       if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY))
1461         {
1462           ; /* good, this is a valid response */
1463         }
1464 #ifdef DBUS_WIN
1465       else if (dbus_message_is_error (message, DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN))
1466         {
1467           /* We are expecting this error, since we know in the test suite we aren't
1468            * talking to a client running on UNIX
1469            */
1470           _dbus_verbose ("Windows correctly does not support GetConnectionUnixProcessID\n");
1471         }
1472 #endif
1473       else
1474         {
1475 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
1476           defined(__linux__) || \
1477           defined(__OpenBSD__)
1478           /* In principle NetBSD should also be in that list, but
1479            * its implementation of PID-passing doesn't work
1480            * over a socketpair() as used in the debug-pipe transport.
1481            * We test this functionality in a more realistic situation
1482            * in test/dbus-daemon.c. */
1483           warn_unexpected (connection, message, "not this error");
1484 
1485           goto out;
1486 #else
1487           _dbus_verbose ("does not support GetConnectionUnixProcessID but perhaps that's OK?\n");
1488 #endif
1489         }
1490     }
1491   else
1492     {
1493 #ifdef DBUS_WIN
1494       warn_unexpected (connection, message, "GetConnectionUnixProcessID to fail on Windows");
1495       goto out;
1496 #else
1497       if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1498         {
1499           ; /* good, expected */
1500         }
1501       else
1502         {
1503           warn_unexpected (connection, message,
1504                            "method_return for GetConnectionUnixProcessID");
1505 
1506           goto out;
1507         }
1508 
1509     retry_get_property:
1510 
1511       if (!dbus_message_get_args (message, &error,
1512                                   DBUS_TYPE_UINT32, &pid,
1513                                   DBUS_TYPE_INVALID))
1514         {
1515           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1516             {
1517               _dbus_verbose ("no memory to get pid by GetConnectionUnixProcessID\n");
1518               dbus_error_free (&error);
1519               _dbus_wait_for_memory ();
1520               goto retry_get_property;
1521             }
1522           else
1523             {
1524               _dbus_assert (dbus_error_is_set (&error));
1525               _dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetConnectionUnixProcessID");
1526               goto out;
1527             }
1528         }
1529       else
1530         {
1531           /* test if returned pid is the same as our own pid
1532            *
1533            * @todo It would probably be good to restructure the tests
1534            *       in a way so our parent is the bus that we're testing
1535            *       cause then we can test that the pid returned matches
1536            *       getppid()
1537            */
1538           if (pid != (dbus_uint32_t) _dbus_getpid ())
1539             {
1540               _dbus_assert (dbus_error_is_set (&error));
1541               _dbus_warn ("Result from GetConnectionUnixProcessID is not our own pid");
1542               goto out;
1543             }
1544         }
1545 #endif /* !DBUS_WIN */
1546     }
1547 
1548   if (!check_no_leftovers (context))
1549     goto out;
1550 
1551   retval = TRUE;
1552 
1553  out:
1554   dbus_error_free (&error);
1555 
1556   if (message)
1557     dbus_message_unref (message);
1558 
1559   return retval;
1560 }
1561 
1562 /* returns TRUE if the correct thing happens,
1563  * but the correct thing may include OOM errors.
1564  */
1565 static dbus_bool_t
check_add_match(BusContext * context,DBusConnection * connection,const char * rule)1566 check_add_match (BusContext     *context,
1567                  DBusConnection *connection,
1568                  const char     *rule)
1569 {
1570   DBusMessage *message;
1571   dbus_bool_t retval;
1572   dbus_uint32_t serial;
1573   DBusError error;
1574 
1575   retval = FALSE;
1576   dbus_error_init (&error);
1577   message = NULL;
1578 
1579   _dbus_verbose ("check_add_match for connection %p, rule %s\n",
1580                  connection, rule);
1581 
1582   message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1583                                           DBUS_PATH_DBUS,
1584                                           DBUS_INTERFACE_DBUS,
1585                                           "AddMatch");
1586 
1587   if (message == NULL)
1588     return TRUE;
1589 
1590   if (!dbus_message_append_args (message, DBUS_TYPE_STRING, &rule,
1591                                  DBUS_TYPE_INVALID))
1592     {
1593       dbus_message_unref (message);
1594       return TRUE;
1595     }
1596 
1597   if (!dbus_connection_send (connection, message, &serial))
1598     {
1599       dbus_message_unref (message);
1600       return TRUE;
1601     }
1602 
1603   dbus_message_unref (message);
1604   message = NULL;
1605 
1606   dbus_connection_ref (connection); /* because we may get disconnected */
1607 
1608   /* send our message */
1609   bus_test_run_clients_loop (SEND_PENDING (connection));
1610 
1611   if (!dbus_connection_get_is_connected (connection))
1612     {
1613       _dbus_verbose ("connection was disconnected\n");
1614 
1615       dbus_connection_unref (connection);
1616 
1617       return TRUE;
1618     }
1619 
1620   block_connection_until_message_from_bus (context, connection, "reply to AddMatch");
1621 
1622   if (!dbus_connection_get_is_connected (connection))
1623     {
1624       _dbus_verbose ("connection was disconnected\n");
1625 
1626       dbus_connection_unref (connection);
1627 
1628       return TRUE;
1629     }
1630 
1631   dbus_connection_unref (connection);
1632 
1633   message = pop_message_waiting_for_memory (connection);
1634   if (message == NULL)
1635     {
1636       _dbus_warn ("Did not receive a reply to %s %d on %p",
1637                   "AddMatch", serial, connection);
1638       goto out;
1639     }
1640 
1641   verbose_message_received (connection, message);
1642 
1643   if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
1644     {
1645       _dbus_warn ("Message has wrong sender %s",
1646                   dbus_message_get_sender (message) ?
1647                   dbus_message_get_sender (message) : "(none)");
1648       goto out;
1649     }
1650 
1651   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1652     {
1653       if (dbus_message_is_error (message,
1654                                  DBUS_ERROR_NO_MEMORY))
1655         {
1656           ; /* good, this is a valid response */
1657         }
1658       else
1659         {
1660           warn_unexpected (connection, message, "not this error");
1661 
1662           goto out;
1663         }
1664     }
1665   else
1666     {
1667       if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1668         {
1669           ; /* good, expected */
1670           _dbus_assert (dbus_message_get_reply_serial (message) == serial);
1671         }
1672       else
1673         {
1674           warn_unexpected (connection, message, "method return for AddMatch");
1675 
1676           goto out;
1677         }
1678     }
1679 
1680   if (!check_no_leftovers (context))
1681     goto out;
1682 
1683   retval = TRUE;
1684 
1685  out:
1686   dbus_error_free (&error);
1687 
1688   if (message)
1689     dbus_message_unref (message);
1690 
1691   return retval;
1692 }
1693 
1694 #ifdef DBUS_ENABLE_STATS
1695 /* returns TRUE if the correct thing happens,
1696  * but the correct thing may include OOM errors.
1697  */
1698 static dbus_bool_t
check_get_all_match_rules(BusContext * context,DBusConnection * connection)1699 check_get_all_match_rules (BusContext     *context,
1700                            DBusConnection *connection)
1701 {
1702   DBusMessage *message;
1703   dbus_bool_t retval;
1704   dbus_uint32_t serial;
1705   DBusError error;
1706 
1707   retval = FALSE;
1708   dbus_error_init (&error);
1709   message = NULL;
1710 
1711   _dbus_verbose ("check_get_all_match_rules for connection %p\n",
1712                  connection);
1713 
1714   message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1715                                           DBUS_PATH_DBUS,
1716                                           BUS_INTERFACE_STATS,
1717                                           "GetAllMatchRules");
1718 
1719   if (message == NULL)
1720     return TRUE;
1721 
1722   if (!dbus_connection_send (connection, message, &serial))
1723     {
1724       dbus_message_unref (message);
1725       return TRUE;
1726     }
1727 
1728   dbus_message_unref (message);
1729   message = NULL;
1730 
1731   dbus_connection_ref (connection); /* because we may get disconnected */
1732 
1733   /* send our message */
1734   bus_test_run_clients_loop (SEND_PENDING (connection));
1735 
1736   if (!dbus_connection_get_is_connected (connection))
1737     {
1738       _dbus_verbose ("connection was disconnected\n");
1739 
1740       dbus_connection_unref (connection);
1741 
1742       return TRUE;
1743     }
1744 
1745   block_connection_until_message_from_bus (context, connection, "reply to AddMatch");
1746 
1747   if (!dbus_connection_get_is_connected (connection))
1748     {
1749       _dbus_verbose ("connection was disconnected\n");
1750 
1751       dbus_connection_unref (connection);
1752 
1753       return TRUE;
1754     }
1755 
1756   dbus_connection_unref (connection);
1757 
1758   message = pop_message_waiting_for_memory (connection);
1759   if (message == NULL)
1760     {
1761       _dbus_warn ("Did not receive a reply to %s %d on %p",
1762                   "AddMatch", serial, connection);
1763       goto out;
1764     }
1765 
1766   verbose_message_received (connection, message);
1767 
1768   if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
1769     {
1770       _dbus_warn ("Message has wrong sender %s",
1771                   dbus_message_get_sender (message) ?
1772                   dbus_message_get_sender (message) : "(none)");
1773       goto out;
1774     }
1775 
1776   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1777     {
1778       if (dbus_message_is_error (message,
1779                                  DBUS_ERROR_NO_MEMORY))
1780         {
1781           ; /* good, this is a valid response */
1782         }
1783       else
1784         {
1785           warn_unexpected (connection, message, "not this error");
1786 
1787           goto out;
1788         }
1789     }
1790   else
1791     {
1792       if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1793         {
1794           ; /* good, expected */
1795           _dbus_assert (dbus_message_get_reply_serial (message) == serial);
1796         }
1797       else
1798         {
1799           warn_unexpected (connection, message, "method return for AddMatch");
1800 
1801           goto out;
1802         }
1803     }
1804 
1805   if (!check_no_leftovers (context))
1806     goto out;
1807 
1808   retval = TRUE;
1809 
1810  out:
1811   dbus_error_free (&error);
1812 
1813   if (message)
1814     dbus_message_unref (message);
1815 
1816   return retval;
1817 }
1818 #endif
1819 
1820 /* returns TRUE if the correct thing happens,
1821  * but the correct thing may include OOM errors.
1822  */
1823 static dbus_bool_t
check_hello_connection(BusContext * context)1824 check_hello_connection (BusContext *context)
1825 {
1826   DBusConnection *connection;
1827   DBusError error;
1828 
1829   dbus_error_init (&error);
1830 
1831   connection = dbus_connection_open_private (TEST_DEBUG_PIPE, &error);
1832   if (connection == NULL)
1833     {
1834       _DBUS_ASSERT_ERROR_IS_SET (&error);
1835       dbus_error_free (&error);
1836       return TRUE;
1837     }
1838 
1839   if (!bus_setup_debug_client (connection))
1840     {
1841       dbus_connection_close (connection);
1842       dbus_connection_unref (connection);
1843       return TRUE;
1844     }
1845 
1846   spin_connection_until_authenticated (context, connection);
1847 
1848   if (!check_hello_message (context, connection))
1849     return FALSE;
1850 
1851   if (dbus_bus_get_unique_name (connection) == NULL)
1852     {
1853       /* We didn't successfully register, so we can't
1854        * do the usual kill_client_connection() checks
1855        */
1856       kill_client_connection_unchecked (connection);
1857     }
1858   else
1859     {
1860       if (!check_add_match (context, connection, ""))
1861         return FALSE;
1862 
1863       kill_client_connection (context, connection);
1864     }
1865 
1866   return TRUE;
1867 }
1868 
1869 #define NONEXISTENT_SERVICE_NAME "test.this.service.does.not.exist.ewuoiurjdfxcvn"
1870 
1871 /* returns TRUE if the correct thing happens,
1872  * but the correct thing may include OOM errors.
1873  */
1874 static dbus_bool_t
check_nonexistent_service_no_auto_start(BusContext * context,DBusConnection * connection)1875 check_nonexistent_service_no_auto_start (BusContext     *context,
1876                                          DBusConnection *connection)
1877 {
1878   DBusMessage *message;
1879   dbus_uint32_t serial;
1880   dbus_bool_t retval;
1881   const char *nonexistent = NONEXISTENT_SERVICE_NAME;
1882   dbus_uint32_t flags;
1883 
1884   message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1885                                           DBUS_PATH_DBUS,
1886                                           DBUS_INTERFACE_DBUS,
1887                                           "StartServiceByName");
1888 
1889   if (message == NULL)
1890     return TRUE;
1891 
1892   dbus_message_set_auto_start (message, FALSE);
1893 
1894   flags = 0;
1895   if (!dbus_message_append_args (message,
1896                                  DBUS_TYPE_STRING, &nonexistent,
1897                                  DBUS_TYPE_UINT32, &flags,
1898                                  DBUS_TYPE_INVALID))
1899     {
1900       dbus_message_unref (message);
1901       return TRUE;
1902     }
1903 
1904   if (!dbus_connection_send (connection, message, &serial))
1905     {
1906       dbus_message_unref (message);
1907       return TRUE;
1908     }
1909 
1910   dbus_message_unref (message);
1911   message = NULL;
1912 
1913   bus_test_run_everything (context);
1914   block_connection_until_message_from_bus (context, connection, "reply to ActivateService on nonexistent");
1915   bus_test_run_everything (context);
1916 
1917   if (!dbus_connection_get_is_connected (connection))
1918     {
1919       _dbus_verbose ("connection was disconnected\n");
1920       return TRUE;
1921     }
1922 
1923   retval = FALSE;
1924 
1925   message = pop_message_waiting_for_memory (connection);
1926   if (message == NULL)
1927     {
1928       _dbus_warn ("Did not receive a reply to %s %d on %p",
1929                   "StartServiceByName", serial, connection);
1930       goto out;
1931     }
1932 
1933   verbose_message_received (connection, message);
1934 
1935   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1936     {
1937       if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
1938         {
1939           _dbus_warn ("Message has wrong sender %s",
1940                       dbus_message_get_sender (message) ?
1941                       dbus_message_get_sender (message) : "(none)");
1942           goto out;
1943         }
1944 
1945       if (dbus_message_is_error (message,
1946                                  DBUS_ERROR_NO_MEMORY))
1947         {
1948           ; /* good, this is a valid response */
1949         }
1950       else if (dbus_message_is_error (message,
1951                                       DBUS_ERROR_SERVICE_UNKNOWN))
1952         {
1953           ; /* good, this is expected also */
1954         }
1955       else
1956         {
1957           warn_unexpected (connection, message, "not this error");
1958           goto out;
1959         }
1960     }
1961   else
1962     {
1963       _dbus_warn ("Did not expect to successfully activate %s",
1964                   NONEXISTENT_SERVICE_NAME);
1965       goto out;
1966     }
1967 
1968   retval = TRUE;
1969 
1970  out:
1971   if (message)
1972     dbus_message_unref (message);
1973 
1974   return retval;
1975 }
1976 
1977 /* returns TRUE if the correct thing happens,
1978  * but the correct thing may include OOM errors.
1979  */
1980 static dbus_bool_t
check_nonexistent_service_auto_start(BusContext * context,DBusConnection * connection)1981 check_nonexistent_service_auto_start (BusContext     *context,
1982                                       DBusConnection *connection)
1983 {
1984   DBusMessage *message;
1985   dbus_uint32_t serial;
1986   dbus_bool_t retval;
1987 
1988   message = dbus_message_new_method_call (NONEXISTENT_SERVICE_NAME,
1989                                           "/org/freedesktop/TestSuite",
1990                                           "org.freedesktop.TestSuite",
1991                                           "Echo");
1992 
1993   if (message == NULL)
1994     return TRUE;
1995 
1996   if (!dbus_connection_send (connection, message, &serial))
1997     {
1998       dbus_message_unref (message);
1999       return TRUE;
2000     }
2001 
2002   dbus_message_unref (message);
2003   message = NULL;
2004 
2005   bus_test_run_everything (context);
2006   block_connection_until_message_from_bus (context, connection, "reply to Echo");
2007   bus_test_run_everything (context);
2008 
2009   if (!dbus_connection_get_is_connected (connection))
2010     {
2011       _dbus_verbose ("connection was disconnected\n");
2012       return TRUE;
2013     }
2014 
2015   retval = FALSE;
2016 
2017   message = pop_message_waiting_for_memory (connection);
2018 
2019   if (message == NULL)
2020     {
2021       _dbus_warn ("Did not receive a reply to %s %d on %p",
2022                   "Echo message (auto activation)", serial, connection);
2023       goto out;
2024     }
2025 
2026   verbose_message_received (connection, message);
2027 
2028   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
2029     {
2030       if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
2031         {
2032           _dbus_warn ("Message has wrong sender %s",
2033                       dbus_message_get_sender (message) ?
2034                       dbus_message_get_sender (message) : "(none)");
2035           goto out;
2036         }
2037 
2038       if (dbus_message_is_error (message,
2039                                  DBUS_ERROR_NO_MEMORY))
2040         {
2041           ; /* good, this is a valid response */
2042         }
2043       else if (dbus_message_is_error (message,
2044                                       DBUS_ERROR_SERVICE_UNKNOWN))
2045         {
2046           ; /* good, this is expected also */
2047         }
2048       else
2049         {
2050           warn_unexpected (connection, message, "not this error");
2051           goto out;
2052         }
2053     }
2054   else
2055     {
2056       _dbus_warn ("Did not expect to successfully activate %s",
2057                   NONEXISTENT_SERVICE_NAME);
2058       goto out;
2059     }
2060 
2061   retval = TRUE;
2062 
2063  out:
2064   if (message)
2065     dbus_message_unref (message);
2066 
2067   return retval;
2068 }
2069 
2070 static dbus_bool_t
check_base_service_activated(BusContext * context,DBusConnection * connection,DBusMessage * initial_message,const char ** base_service_p)2071 check_base_service_activated (BusContext     *context,
2072                               DBusConnection *connection,
2073                               DBusMessage    *initial_message,
2074                               const char    **base_service_p)
2075 {
2076   DBusMessage *message;
2077   dbus_bool_t retval;
2078   DBusError error;
2079   const char *base_service, *base_service_from_bus, *old_owner;
2080 
2081   retval = FALSE;
2082 
2083   dbus_error_init (&error);
2084   base_service = NULL;
2085   old_owner = NULL;
2086   base_service_from_bus = NULL;
2087 
2088   message = initial_message;
2089   dbus_message_ref (message);
2090 
2091   if (dbus_message_is_signal (message,
2092                               DBUS_INTERFACE_DBUS,
2093                               "NameOwnerChanged"))
2094     {
2095       CheckServiceOwnerChangedData socd;
2096 
2097     reget_service_name_arg:
2098       base_service = NULL;
2099       old_owner = NULL;
2100       base_service_from_bus = NULL;
2101 
2102       if (!dbus_message_get_args (message, &error,
2103                                   DBUS_TYPE_STRING, &base_service,
2104                                   DBUS_TYPE_STRING, &old_owner,
2105                                   DBUS_TYPE_STRING, &base_service_from_bus,
2106                                   DBUS_TYPE_INVALID))
2107         {
2108           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
2109             {
2110               dbus_error_free (&error);
2111               _dbus_wait_for_memory ();
2112               goto reget_service_name_arg;
2113             }
2114           else
2115             {
2116               _dbus_warn ("Message %s doesn't have a service name: %s",
2117                           "NameOwnerChanged (creation)",
2118                           error.message);
2119               goto out;
2120             }
2121         }
2122 
2123       if (*base_service != ':')
2124         {
2125           _dbus_warn ("Expected base service activation, got \"%s\" instead",
2126                       base_service);
2127           goto out;
2128         }
2129 
2130       if (strcmp (base_service, base_service_from_bus) != 0)
2131         {
2132           _dbus_warn ("Expected base service activation, got \"%s\" instead with owner \"%s\"",
2133                       base_service, base_service_from_bus);
2134           goto out;
2135         }
2136 
2137       if (old_owner[0])
2138         {
2139           _dbus_warn ("Received an old_owner argument during base service activation, \"%s\"",
2140                       old_owner);
2141           goto out;
2142         }
2143 
2144       socd.expected_kind = SERVICE_CREATED;
2145       socd.expected_service_name = base_service;
2146       socd.failed = FALSE;
2147       socd.skip_connection = connection;
2148       socd.context = context;
2149 
2150       bus_test_clients_foreach (check_service_owner_changed_foreach,
2151                                 &socd);
2152 
2153       if (socd.failed)
2154         goto out;
2155     }
2156   else
2157     {
2158       warn_unexpected (connection, message, "NameOwnerChanged (creation) for base service");
2159 
2160       goto out;
2161     }
2162 
2163   if (base_service_p)
2164     *base_service_p = base_service;
2165 
2166   retval = TRUE;
2167 
2168  out:
2169   if (message)
2170     dbus_message_unref (message);
2171   dbus_error_free (&error);
2172 
2173   return retval;
2174 }
2175 
2176 static dbus_bool_t
check_service_activated(BusContext * context,DBusConnection * connection,const char * activated_name,const char * base_service_name,DBusMessage * initial_message)2177 check_service_activated (BusContext     *context,
2178                          DBusConnection *connection,
2179                          const char     *activated_name,
2180                          const char     *base_service_name,
2181                          DBusMessage    *initial_message)
2182 {
2183   DBusMessage *message;
2184   dbus_bool_t retval;
2185   DBusError error;
2186   dbus_uint32_t activation_result;
2187 
2188   retval = FALSE;
2189 
2190   dbus_error_init (&error);
2191 
2192   message = initial_message;
2193   dbus_message_ref (message);
2194 
2195   if (dbus_message_is_signal (message,
2196                               DBUS_INTERFACE_DBUS,
2197                               "NameOwnerChanged"))
2198     {
2199       CheckServiceOwnerChangedData socd;
2200       const char *service_name, *base_service_from_bus, *old_owner;
2201 
2202     reget_service_name_arg:
2203       service_name = NULL;
2204       old_owner = NULL;
2205       base_service_from_bus = NULL;
2206 
2207       if (!dbus_message_get_args (message, &error,
2208                                   DBUS_TYPE_STRING, &service_name,
2209                                    DBUS_TYPE_STRING, &old_owner,
2210                                   DBUS_TYPE_STRING, &base_service_from_bus,
2211                                   DBUS_TYPE_INVALID))
2212         {
2213           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
2214             {
2215               dbus_error_free (&error);
2216               _dbus_wait_for_memory ();
2217               goto reget_service_name_arg;
2218             }
2219           else
2220             {
2221               _dbus_warn ("Message %s doesn't have a service name: %s",
2222                           "NameOwnerChanged (creation)",
2223                           error.message);
2224               goto out;
2225             }
2226         }
2227 
2228       if (strcmp (service_name, activated_name) != 0)
2229         {
2230           _dbus_warn ("Expected to see service %s created, saw %s instead",
2231                       activated_name, service_name);
2232           goto out;
2233         }
2234 
2235       if (strcmp (base_service_name, base_service_from_bus) != 0)
2236         {
2237           _dbus_warn ("NameOwnerChanged reports wrong base service: %s owner, expected %s instead",
2238                       base_service_from_bus, base_service_name);
2239           goto out;
2240         }
2241 
2242       if (old_owner[0])
2243         {
2244           _dbus_warn ("expected a %s, got a %s",
2245                       "NameOwnerChanged (creation)",
2246                       "NameOwnerChanged (change)");
2247           goto out;
2248         }
2249 
2250       socd.expected_kind = SERVICE_CREATED;
2251       socd.skip_connection = connection;
2252       socd.failed = FALSE;
2253       socd.expected_service_name = service_name;
2254       socd.context = context;
2255 
2256       bus_test_clients_foreach (check_service_owner_changed_foreach,
2257                                 &socd);
2258 
2259       if (socd.failed)
2260         goto out;
2261 
2262       dbus_message_unref (message);
2263       service_name = NULL;
2264       old_owner = NULL;
2265       base_service_from_bus = NULL;
2266 
2267       message = pop_message_waiting_for_memory (connection);
2268       if (message == NULL)
2269         {
2270           _dbus_warn ("Expected a reply to %s, got nothing",
2271                       "StartServiceByName");
2272           goto out;
2273         }
2274     }
2275   else
2276     {
2277       warn_unexpected (connection, message, "NameOwnerChanged for the activated name");
2278 
2279       goto out;
2280     }
2281 
2282   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
2283     {
2284       warn_unexpected (connection, message, "reply to StartServiceByName");
2285 
2286       goto out;
2287     }
2288 
2289   activation_result = 0;
2290   if (!dbus_message_get_args (message, &error,
2291                               DBUS_TYPE_UINT32, &activation_result,
2292                               DBUS_TYPE_INVALID))
2293     {
2294       if (!dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
2295         {
2296           _dbus_warn ("Did not have activation result first argument to %s: %s",
2297                       "StartServiceByName", error.message);
2298           goto out;
2299         }
2300 
2301       dbus_error_free (&error);
2302     }
2303   else
2304     {
2305       if (activation_result == DBUS_START_REPLY_SUCCESS)
2306         ; /* Good */
2307       else if (activation_result == DBUS_START_REPLY_ALREADY_RUNNING)
2308         ; /* Good also */
2309       else
2310         {
2311           _dbus_warn ("Activation result was %u, no good.",
2312                       activation_result);
2313           goto out;
2314         }
2315     }
2316 
2317   dbus_message_unref (message);
2318   message = NULL;
2319 
2320   if (!check_no_leftovers (context))
2321     {
2322       _dbus_warn ("Messages were left over after verifying existent activation results");
2323       goto out;
2324     }
2325 
2326   retval = TRUE;
2327 
2328  out:
2329   if (message)
2330     dbus_message_unref (message);
2331   dbus_error_free (&error);
2332 
2333   return retval;
2334 }
2335 
2336 static dbus_bool_t
check_service_auto_activated(BusContext * context,DBusConnection * connection,const char * activated_name,const char * base_service_name,DBusMessage * initial_message)2337 check_service_auto_activated (BusContext     *context,
2338                               DBusConnection *connection,
2339                               const char     *activated_name,
2340                               const char     *base_service_name,
2341                               DBusMessage    *initial_message)
2342 {
2343   DBusMessage *message;
2344   dbus_bool_t retval;
2345   DBusError error;
2346 
2347   retval = FALSE;
2348 
2349   dbus_error_init (&error);
2350 
2351   message = initial_message;
2352   dbus_message_ref (message);
2353 
2354   if (dbus_message_is_signal (message,
2355                               DBUS_INTERFACE_DBUS,
2356                               "NameOwnerChanged"))
2357     {
2358       const char *service_name;
2359       CheckServiceOwnerChangedData socd;
2360 
2361     reget_service_name_arg:
2362       if (!dbus_message_get_args (message, &error,
2363                                   DBUS_TYPE_STRING, &service_name,
2364                                   DBUS_TYPE_INVALID))
2365         {
2366           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
2367             {
2368               dbus_error_free (&error);
2369               _dbus_wait_for_memory ();
2370               goto reget_service_name_arg;
2371             }
2372           else
2373             {
2374               _dbus_warn ("Message %s doesn't have a service name: %s",
2375                           "NameOwnerChanged",
2376                           error.message);
2377               dbus_error_free (&error);
2378               goto out;
2379             }
2380         }
2381 
2382       if (strcmp (service_name, activated_name) != 0)
2383         {
2384           _dbus_warn ("Expected to see service %s created, saw %s instead",
2385                       activated_name, service_name);
2386           goto out;
2387         }
2388 
2389       socd.expected_kind = SERVICE_CREATED;
2390       socd.expected_service_name = service_name;
2391       socd.failed = FALSE;
2392       socd.skip_connection = connection;
2393       socd.context = context;
2394 
2395       bus_test_clients_foreach (check_service_owner_changed_foreach,
2396                                 &socd);
2397 
2398       if (socd.failed)
2399         goto out;
2400 
2401       /* Note that this differs from regular activation in that we don't get a
2402        * reply to ActivateService here.
2403        */
2404 
2405       dbus_message_unref (message);
2406       message = NULL;
2407       service_name = NULL;
2408     }
2409   else
2410     {
2411       warn_unexpected (connection, message, "NameOwnerChanged for the activated name");
2412 
2413       goto out;
2414     }
2415 
2416   retval = TRUE;
2417 
2418  out:
2419   if (message)
2420     dbus_message_unref (message);
2421 
2422   return retval;
2423 }
2424 
2425 static dbus_bool_t
check_service_deactivated(BusContext * context,DBusConnection * connection,const char * activated_name,const char * base_service)2426 check_service_deactivated (BusContext     *context,
2427                            DBusConnection *connection,
2428                            const char     *activated_name,
2429                            const char     *base_service)
2430 {
2431   dbus_bool_t retval;
2432   CheckServiceOwnerChangedData socd;
2433 
2434   retval = FALSE;
2435 
2436   /* Now we are expecting ServiceOwnerChanged (deletion) messages for the base
2437    * service and the activated_name.  The base service
2438    * notification is required to come last.
2439    */
2440   socd.expected_kind = SERVICE_DELETED;
2441   socd.expected_service_name = activated_name;
2442   socd.failed = FALSE;
2443   socd.skip_connection = NULL;
2444   socd.context = context;
2445 
2446   bus_test_clients_foreach (check_service_owner_changed_foreach,
2447                             &socd);
2448 
2449   if (socd.failed)
2450     goto out;
2451 
2452   socd.expected_kind = SERVICE_DELETED;
2453   socd.expected_service_name = base_service;
2454   socd.failed = FALSE;
2455   socd.skip_connection = NULL;
2456   socd.context = context;
2457 
2458   bus_test_clients_foreach (check_service_owner_changed_foreach,
2459                             &socd);
2460 
2461   if (socd.failed)
2462     goto out;
2463 
2464   retval = TRUE;
2465 
2466  out:
2467   return retval;
2468 }
2469 
2470 static dbus_bool_t
check_send_exit_to_service(BusContext * context,DBusConnection * connection,const char * service_name,const char * base_service)2471 check_send_exit_to_service (BusContext     *context,
2472                             DBusConnection *connection,
2473                             const char     *service_name,
2474                             const char     *base_service)
2475 {
2476   dbus_bool_t got_error;
2477   DBusMessage *message;
2478   dbus_uint32_t serial;
2479   dbus_bool_t retval;
2480 
2481   _dbus_verbose ("Sending exit message to the test service\n");
2482 
2483   retval = FALSE;
2484 
2485   /* Kill off the test service by sending it a quit message */
2486   message = dbus_message_new_method_call (service_name,
2487                                           "/org/freedesktop/TestSuite",
2488                                           "org.freedesktop.TestSuite",
2489                                           "Exit");
2490 
2491   if (message == NULL)
2492     {
2493       /* Do this again; we still need the service to exit... */
2494       if (!check_send_exit_to_service (context, connection,
2495                                        service_name, base_service))
2496         goto out;
2497 
2498       return TRUE;
2499     }
2500 
2501   if (!dbus_connection_send (connection, message, &serial))
2502     {
2503       dbus_message_unref (message);
2504 
2505       /* Do this again; we still need the service to exit... */
2506       if (!check_send_exit_to_service (context, connection,
2507                                        service_name, base_service))
2508         goto out;
2509 
2510       return TRUE;
2511     }
2512 
2513   dbus_message_unref (message);
2514   message = NULL;
2515 
2516   /* send message */
2517   bus_test_run_clients_loop (SEND_PENDING (connection));
2518 
2519   /* read it in and write it out to test service */
2520   bus_test_run_bus_loop (context, FALSE);
2521 
2522   /* see if we got an error during message bus dispatching */
2523   bus_test_run_clients_loop (FALSE);
2524   message = borrow_message_waiting_for_memory (connection);
2525   got_error = message != NULL && dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR;
2526   if (message)
2527     {
2528       dbus_connection_return_message (connection, message);
2529       message = NULL;
2530     }
2531 
2532   if (!got_error)
2533     {
2534       /* If no error, wait for the test service to exit */
2535       block_connection_until_message_from_bus (context, connection, "test service to exit");
2536 
2537       bus_test_run_everything (context);
2538     }
2539 
2540   if (got_error)
2541     {
2542       message = pop_message_waiting_for_memory (connection);
2543       _dbus_assert (message != NULL);
2544 
2545       if (dbus_message_get_reply_serial (message) != serial)
2546         {
2547           warn_unexpected (connection, message,
2548                            "error with the correct reply serial");
2549           goto out;
2550         }
2551 
2552       if (!dbus_message_is_error (message,
2553                                   DBUS_ERROR_NO_MEMORY))
2554         {
2555           warn_unexpected (connection, message,
2556                            "a no memory error from asking test service to exit");
2557           goto out;
2558         }
2559 
2560       _dbus_verbose ("Got error %s when asking test service to exit\n",
2561                      dbus_message_get_error_name (message));
2562 
2563       /* Do this again; we still need the service to exit... */
2564       if (!check_send_exit_to_service (context, connection,
2565                                        service_name, base_service))
2566         goto out;
2567     }
2568   else
2569     {
2570       if (!check_service_deactivated (context, connection,
2571                                       service_name, base_service))
2572         goto out;
2573 
2574       /* Should now have a NoReply error from the Exit() method
2575        * call; it should have come after all the deactivation
2576        * stuff.
2577        */
2578       message = pop_message_waiting_for_memory (connection);
2579 
2580       if (message == NULL)
2581         {
2582           warn_unexpected (connection, NULL,
2583                            "reply to Exit() method call");
2584           goto out;
2585         }
2586       if (!dbus_message_is_error (message,
2587                                   DBUS_ERROR_NO_REPLY))
2588         {
2589           warn_unexpected (connection, message,
2590                            "NoReply error from Exit() method call");
2591           goto out;
2592         }
2593 
2594       if (dbus_message_get_reply_serial (message) != serial)
2595         {
2596           warn_unexpected (connection, message,
2597                            "error with the correct reply serial");
2598           goto out;
2599         }
2600 
2601       _dbus_verbose ("Got error %s after test service exited\n",
2602                      dbus_message_get_error_name (message));
2603 
2604       if (!check_no_leftovers (context))
2605         {
2606           _dbus_warn ("Messages were left over after %s",
2607                       _DBUS_FUNCTION_NAME);
2608           goto out;
2609         }
2610     }
2611 
2612   retval = TRUE;
2613 
2614  out:
2615   if (message)
2616     dbus_message_unref (message);
2617 
2618   return retval;
2619 }
2620 
2621 static dbus_bool_t
check_got_error(BusContext * context,DBusConnection * connection,const char * first_error_name,...)2622 check_got_error (BusContext     *context,
2623                  DBusConnection *connection,
2624                  const char     *first_error_name,
2625                  ...)
2626 {
2627   DBusMessage *message;
2628   dbus_bool_t retval;
2629   va_list ap;
2630   dbus_bool_t error_found;
2631   const char *error_name;
2632 
2633   retval = FALSE;
2634 
2635   message = pop_message_waiting_for_memory (connection);
2636   if (message == NULL)
2637     {
2638       _dbus_warn ("Did not get an expected error");
2639       goto out;
2640     }
2641 
2642   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
2643     {
2644       warn_unexpected (connection, message, "an error");
2645 
2646       goto out;
2647     }
2648 
2649   error_found = FALSE;
2650 
2651   va_start (ap, first_error_name);
2652   error_name = first_error_name;
2653   while (error_name != NULL)
2654     {
2655       if (dbus_message_is_error (message, error_name))
2656         {
2657           error_found = TRUE;
2658           break;
2659         }
2660       error_name = va_arg (ap, char*);
2661     }
2662   va_end (ap);
2663 
2664   if (!error_found)
2665     {
2666       _dbus_warn ("Expected error %s or other, got %s instead",
2667                   first_error_name,
2668                   dbus_message_get_error_name (message));
2669       goto out;
2670     }
2671 
2672   retval = TRUE;
2673 
2674  out:
2675   if (message)
2676     dbus_message_unref (message);
2677 
2678   return retval;
2679 }
2680 
2681 typedef enum
2682 {
2683   GOT_SERVICE_CREATED,
2684   GOT_SERVICE_DELETED,
2685   GOT_ERROR,
2686   GOT_SOMETHING_ELSE
2687 } GotServiceInfo;
2688 
2689 static GotServiceInfo
check_got_service_info(DBusMessage * message)2690 check_got_service_info (DBusMessage *message)
2691 {
2692   GotServiceInfo message_kind;
2693 
2694   if (dbus_message_is_signal (message,
2695                               DBUS_INTERFACE_DBUS,
2696                               "NameOwnerChanged"))
2697     {
2698       DBusError error;
2699       const char *service_name, *old_owner, *new_owner;
2700       dbus_error_init (&error);
2701 
2702     reget_service_info_data:
2703       service_name = NULL;
2704       old_owner = NULL;
2705       new_owner = NULL;
2706 
2707       dbus_message_get_args (message, &error,
2708                              DBUS_TYPE_STRING, &service_name,
2709                              DBUS_TYPE_STRING, &old_owner,
2710                              DBUS_TYPE_STRING, &new_owner,
2711                              DBUS_TYPE_INVALID);
2712       if (dbus_error_is_set (&error))
2713         {
2714           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
2715             {
2716               dbus_error_free (&error);
2717               goto reget_service_info_data;
2718             }
2719           else
2720             {
2721               _dbus_warn ("unexpected arguments for NameOwnerChanged message");
2722               message_kind = GOT_SOMETHING_ELSE;
2723             }
2724         }
2725       else if (!old_owner[0])
2726         message_kind = GOT_SERVICE_CREATED;
2727       else if (!new_owner[0])
2728         message_kind = GOT_SERVICE_DELETED;
2729       else
2730         message_kind = GOT_SOMETHING_ELSE;
2731 
2732       dbus_error_free (&error);
2733     }
2734   else if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
2735     message_kind = GOT_ERROR;
2736   else
2737     message_kind = GOT_SOMETHING_ELSE;
2738 
2739   return message_kind;
2740 }
2741 
2742 #define EXISTENT_SERVICE_NAME "org.freedesktop.DBus.TestSuiteEchoService"
2743 
2744 /* returns TRUE if the correct thing happens,
2745  * but the correct thing may include OOM errors.
2746  */
2747 static dbus_bool_t
check_existent_service_no_auto_start(BusContext * context,DBusConnection * connection)2748 check_existent_service_no_auto_start (BusContext     *context,
2749                                       DBusConnection *connection)
2750 {
2751   DBusMessage *message;
2752   DBusMessage *base_service_message;
2753   const char *base_service;
2754   dbus_uint32_t serial;
2755   dbus_bool_t retval;
2756   const char *existent = EXISTENT_SERVICE_NAME;
2757   dbus_uint32_t flags;
2758 
2759   base_service_message = NULL;
2760 
2761   message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
2762                                           DBUS_PATH_DBUS,
2763                                           DBUS_INTERFACE_DBUS,
2764                                           "StartServiceByName");
2765 
2766   if (message == NULL)
2767     return TRUE;
2768 
2769   dbus_message_set_auto_start (message, FALSE);
2770 
2771   flags = 0;
2772   if (!dbus_message_append_args (message,
2773                                  DBUS_TYPE_STRING, &existent,
2774                                  DBUS_TYPE_UINT32, &flags,
2775                                  DBUS_TYPE_INVALID))
2776     {
2777       dbus_message_unref (message);
2778       return TRUE;
2779     }
2780 
2781   if (!dbus_connection_send (connection, message, &serial))
2782     {
2783       dbus_message_unref (message);
2784       return TRUE;
2785     }
2786 
2787   dbus_message_unref (message);
2788   message = NULL;
2789 
2790   bus_test_run_everything (context);
2791 
2792   /* now wait for the message bus to hear back from the activated
2793    * service.
2794    */
2795   block_connection_until_message_from_bus (context, connection, "activated service to connect");
2796 
2797   bus_test_run_everything (context);
2798 
2799   if (!dbus_connection_get_is_connected (connection))
2800     {
2801       _dbus_verbose ("connection was disconnected\n");
2802       return TRUE;
2803     }
2804 
2805   retval = FALSE;
2806 
2807   message = pop_message_waiting_for_memory (connection);
2808   if (message == NULL)
2809     {
2810       _dbus_warn ("Did not receive any messages after %s %d on %p",
2811                   "StartServiceByName", serial, connection);
2812       goto out;
2813     }
2814 
2815   verbose_message_received (connection, message);
2816   _dbus_verbose ("  (after sending %s)\n", "StartServiceByName");
2817 
2818   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
2819     {
2820       if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
2821         {
2822           _dbus_warn ("Message has wrong sender %s",
2823                       dbus_message_get_sender (message) ?
2824                       dbus_message_get_sender (message) : "(none)");
2825           goto out;
2826         }
2827 
2828       if (dbus_message_is_error (message,
2829                                  DBUS_ERROR_NO_MEMORY))
2830         {
2831           ; /* good, this is a valid response */
2832         }
2833       else if (dbus_message_is_error (message,
2834                                       DBUS_ERROR_SPAWN_CHILD_EXITED) ||
2835                dbus_message_is_error (message,
2836                                       DBUS_ERROR_SPAWN_CHILD_SIGNALED) ||
2837                dbus_message_is_error (message,
2838                                       DBUS_ERROR_SPAWN_EXEC_FAILED))
2839         {
2840           ; /* good, this is expected also */
2841         }
2842       else
2843         {
2844           _dbus_warn ("Did not expect error %s",
2845                       dbus_message_get_error_name (message));
2846           goto out;
2847         }
2848     }
2849   else
2850     {
2851       GotServiceInfo message_kind;
2852 
2853       if (!check_base_service_activated (context, connection,
2854                                          message, &base_service))
2855         goto out;
2856 
2857       base_service_message = message;
2858       message = NULL;
2859 
2860       /* We may need to block here for the test service to exit or finish up */
2861       block_connection_until_message_from_bus (context, connection, "test service to exit or finish up");
2862 
2863       message = dbus_connection_borrow_message (connection);
2864       if (message == NULL)
2865         {
2866           _dbus_warn ("Did not receive any messages after base service creation notification");
2867           goto out;
2868         }
2869 
2870       message_kind = check_got_service_info (message);
2871 
2872       dbus_connection_return_message (connection, message);
2873       message = NULL;
2874 
2875       switch (message_kind)
2876         {
2877         case GOT_SOMETHING_ELSE:
2878         default:
2879           _dbus_warn ("Unexpected message after ActivateService "
2880                       "(should be an error or a service announcement");
2881           goto out;
2882 
2883         case GOT_ERROR:
2884           if (!check_got_error (context, connection,
2885                                 DBUS_ERROR_SPAWN_CHILD_EXITED,
2886                                 DBUS_ERROR_NO_MEMORY,
2887                                 NULL))
2888             goto out;
2889           /* A service deleted should be coming along now after this error.
2890            * We can also get the error *after* the service deleted.
2891            */
2892 
2893           /* fall through */
2894 
2895         case GOT_SERVICE_DELETED:
2896           {
2897             /* The service started up and got a base address, but then
2898              * failed to register under EXISTENT_SERVICE_NAME
2899              */
2900             CheckServiceOwnerChangedData socd;
2901 
2902             socd.expected_kind = SERVICE_DELETED;
2903             socd.expected_service_name = base_service;
2904             socd.failed = FALSE;
2905             socd.skip_connection = NULL;
2906             socd.context = context;
2907 
2908             bus_test_clients_foreach (check_service_owner_changed_foreach,
2909                                       &socd);
2910 
2911             if (socd.failed)
2912               goto out;
2913 
2914             /* Now we should get an error about the service exiting
2915              * if we didn't get it before.
2916              */
2917             if (message_kind != GOT_ERROR)
2918               {
2919                 block_connection_until_message_from_bus (context, connection, "error about service exiting");
2920 
2921                 /* and process everything again */
2922                 bus_test_run_everything (context);
2923 
2924                 if (!check_got_error (context, connection,
2925                                       DBUS_ERROR_SPAWN_CHILD_EXITED,
2926 				      DBUS_ERROR_NO_MEMORY,
2927                                       NULL))
2928                   goto out;
2929               }
2930             break;
2931           }
2932 
2933         case GOT_SERVICE_CREATED:
2934           message = pop_message_waiting_for_memory (connection);
2935           if (message == NULL)
2936             {
2937               _dbus_warn ("Failed to pop message we just put back! "
2938                           "should have been a NameOwnerChanged (creation)");
2939               goto out;
2940             }
2941 
2942           if (!check_service_activated (context, connection, EXISTENT_SERVICE_NAME,
2943                                         base_service, message))
2944             goto out;
2945 
2946           dbus_message_unref (message);
2947           message = NULL;
2948 
2949           if (!check_no_leftovers (context))
2950             {
2951               _dbus_warn ("Messages were left over after successful activation");
2952               goto out;
2953             }
2954 
2955 	  if (!check_send_exit_to_service (context, connection,
2956                                            EXISTENT_SERVICE_NAME, base_service))
2957 	    goto out;
2958 
2959           break;
2960         }
2961     }
2962 
2963   retval = TRUE;
2964 
2965  out:
2966   if (message)
2967     dbus_message_unref (message);
2968 
2969   if (base_service_message)
2970     dbus_message_unref (base_service_message);
2971 
2972   return retval;
2973 }
2974 
2975 /* returns TRUE if the correct thing happens,
2976  * but the correct thing may include OOM errors.
2977  */
2978 static dbus_bool_t
check_segfault_service_no_auto_start(BusContext * context,DBusConnection * connection)2979 check_segfault_service_no_auto_start (BusContext     *context,
2980                                       DBusConnection *connection)
2981 {
2982   DBusMessage *message;
2983   dbus_uint32_t serial;
2984   dbus_bool_t retval;
2985   const char *segv_service;
2986   dbus_uint32_t flags;
2987 
2988   message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
2989                                           DBUS_PATH_DBUS,
2990                                           DBUS_INTERFACE_DBUS,
2991                                           "StartServiceByName");
2992 
2993   if (message == NULL)
2994     return TRUE;
2995 
2996   dbus_message_set_auto_start (message, FALSE);
2997 
2998   segv_service = "org.freedesktop.DBus.TestSuiteSegfaultService";
2999   flags = 0;
3000   if (!dbus_message_append_args (message,
3001                                  DBUS_TYPE_STRING, &segv_service,
3002                                  DBUS_TYPE_UINT32, &flags,
3003                                  DBUS_TYPE_INVALID))
3004     {
3005       dbus_message_unref (message);
3006       return TRUE;
3007     }
3008 
3009   if (!dbus_connection_send (connection, message, &serial))
3010     {
3011       dbus_message_unref (message);
3012       return TRUE;
3013     }
3014 
3015   dbus_message_unref (message);
3016   message = NULL;
3017 
3018   bus_test_run_everything (context);
3019   block_connection_until_message_from_bus (context, connection, "reply to activating segfault service");
3020   bus_test_run_everything (context);
3021 
3022   if (!dbus_connection_get_is_connected (connection))
3023     {
3024       _dbus_verbose ("connection was disconnected\n");
3025       return TRUE;
3026     }
3027 
3028   retval = FALSE;
3029 
3030   message = pop_message_waiting_for_memory (connection);
3031   if (message == NULL)
3032     {
3033       _dbus_warn ("Did not receive a reply to %s %d on %p",
3034                   "StartServiceByName", serial, connection);
3035       goto out;
3036     }
3037 
3038   verbose_message_received (connection, message);
3039 
3040   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
3041     {
3042       if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
3043         {
3044           _dbus_warn ("Message has wrong sender %s",
3045                       dbus_message_get_sender (message) ?
3046                       dbus_message_get_sender (message) : "(none)");
3047           goto out;
3048         }
3049 
3050       if (dbus_message_is_error (message,
3051                                  DBUS_ERROR_NO_MEMORY))
3052         {
3053           ; /* good, this is a valid response */
3054         }
3055       else if (dbus_message_is_error (message,
3056                                       DBUS_ERROR_FAILED))
3057         {
3058           const char *servicehelper;
3059           servicehelper = bus_context_get_servicehelper (context);
3060           /* make sure this only happens with the launch helper */
3061           _dbus_assert (servicehelper != NULL);
3062         }
3063 #ifdef DBUS_WIN
3064       else if (dbus_message_is_error (message,
3065                                       DBUS_ERROR_SPAWN_CHILD_EXITED))
3066         {
3067           /* unhandled exceptions are normal exit codes */
3068         }
3069 #else
3070       else if (dbus_message_is_error (message,
3071                                       DBUS_ERROR_SPAWN_CHILD_SIGNALED))
3072         {
3073           ; /* good, this is expected also */
3074         }
3075 #endif
3076       else
3077         {
3078           warn_unexpected (connection, message, "not this error");
3079 
3080           goto out;
3081         }
3082     }
3083   else
3084     {
3085       _dbus_warn ("Did not expect to successfully activate segfault service");
3086       goto out;
3087     }
3088 
3089   retval = TRUE;
3090 
3091  out:
3092   if (message)
3093     dbus_message_unref (message);
3094 
3095   return retval;
3096 }
3097 
3098 
3099 /* returns TRUE if the correct thing happens,
3100  * but the correct thing may include OOM errors.
3101  */
3102 static dbus_bool_t
check_segfault_service_auto_start(BusContext * context,DBusConnection * connection)3103 check_segfault_service_auto_start (BusContext     *context,
3104                                    DBusConnection *connection)
3105 {
3106   DBusMessage *message;
3107   dbus_uint32_t serial;
3108   dbus_bool_t retval;
3109 
3110   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteSegfaultService",
3111                                           "/org/freedesktop/TestSuite",
3112                                           "org.freedesktop.TestSuite",
3113                                           "Echo");
3114 
3115   if (message == NULL)
3116     return TRUE;
3117 
3118   if (!dbus_connection_send (connection, message, &serial))
3119     {
3120       dbus_message_unref (message);
3121       return TRUE;
3122     }
3123 
3124   dbus_message_unref (message);
3125   message = NULL;
3126 
3127   bus_test_run_everything (context);
3128   block_connection_until_message_from_bus (context, connection, "reply to Echo on segfault service");
3129   bus_test_run_everything (context);
3130 
3131   if (!dbus_connection_get_is_connected (connection))
3132     {
3133       _dbus_verbose ("connection was disconnected\n");
3134       return TRUE;
3135     }
3136 
3137   retval = FALSE;
3138 
3139   message = pop_message_waiting_for_memory (connection);
3140   if (message == NULL)
3141     {
3142       _dbus_warn ("Did not receive a reply to %s %d on %p",
3143                   "Echo message (auto activation)", serial, connection);
3144       goto out;
3145     }
3146 
3147   verbose_message_received (connection, message);
3148 
3149   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
3150     {
3151       if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
3152         {
3153           _dbus_warn ("Message has wrong sender %s",
3154                       dbus_message_get_sender (message) ?
3155                       dbus_message_get_sender (message) : "(none)");
3156           goto out;
3157         }
3158 
3159       if (dbus_message_is_error (message,
3160                                  DBUS_ERROR_NO_MEMORY))
3161         {
3162           ; /* good, this is a valid response */
3163         }
3164 #ifdef DBUS_WIN
3165       else if (dbus_message_is_error (message,
3166                                       DBUS_ERROR_SPAWN_CHILD_EXITED))
3167         {
3168           /* unhandled exceptions are normal exit codes */
3169         }
3170 #else
3171       else if (dbus_message_is_error (message,
3172                                       DBUS_ERROR_SPAWN_CHILD_SIGNALED))
3173         {
3174           ; /* good, this is expected also */
3175         }
3176 #endif
3177       else
3178         {
3179           warn_unexpected (connection, message, "not this error");
3180 
3181           goto out;
3182         }
3183     }
3184   else
3185     {
3186       _dbus_warn ("Did not expect to successfully activate segfault service");
3187       goto out;
3188     }
3189 
3190   retval = TRUE;
3191 
3192  out:
3193   if (message)
3194     dbus_message_unref (message);
3195 
3196   return retval;
3197 }
3198 
3199 #define TEST_ECHO_MESSAGE "Test echo message"
3200 #define TEST_RUN_HELLO_FROM_SELF_MESSAGE "Test sending message to self"
3201 
3202 /* returns TRUE if the correct thing happens,
3203  * but the correct thing may include OOM errors.
3204  */
3205 static dbus_bool_t
check_existent_hello_from_self(BusContext * context,DBusConnection * connection)3206 check_existent_hello_from_self (BusContext     *context,
3207                                 DBusConnection *connection)
3208 {
3209   DBusMessage *message;
3210   dbus_uint32_t serial;
3211   const char *text;
3212 
3213   message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
3214                                           "/org/freedesktop/TestSuite",
3215                                           "org.freedesktop.TestSuite",
3216                                           "RunHelloFromSelf");
3217 
3218   if (message == NULL)
3219     return TRUE;
3220 
3221   text = TEST_RUN_HELLO_FROM_SELF_MESSAGE;
3222   if (!dbus_message_append_args (message,
3223                                  DBUS_TYPE_STRING, &text,
3224                                  DBUS_TYPE_INVALID))
3225     {
3226       dbus_message_unref (message);
3227       return TRUE;
3228     }
3229 
3230   if (!dbus_connection_send (connection, message, &serial))
3231     {
3232       dbus_message_unref (message);
3233       return TRUE;
3234     }
3235 
3236   dbus_message_unref (message);
3237   message = NULL;
3238 
3239   bus_test_run_everything (context);
3240 
3241   /* Note: if this test is run in OOM mode, it will block when the bus
3242    * doesn't send a reply due to OOM.
3243    */
3244   block_connection_until_message_from_bus (context, connection, "reply from running hello from self");
3245 
3246   message = pop_message_waiting_for_memory (connection);
3247   if (message == NULL)
3248     {
3249       _dbus_warn ("Failed to pop message! Should have been reply from RunHelloFromSelf message");
3250       return FALSE;
3251     }
3252 
3253   if (dbus_message_get_reply_serial (message) != serial)
3254     {
3255       _dbus_warn ("Wrong reply serial");
3256       dbus_message_unref (message);
3257       return FALSE;
3258     }
3259 
3260   dbus_message_unref (message);
3261   message = NULL;
3262 
3263   return TRUE;
3264 }
3265 
3266 /* returns TRUE if the correct thing happens,
3267  * but the correct thing may include OOM errors.
3268  */
3269 static dbus_bool_t
check_existent_ping(BusContext * context,DBusConnection * connection)3270 check_existent_ping (BusContext     *context,
3271                      DBusConnection *connection)
3272 {
3273   DBusMessage *message;
3274   dbus_uint32_t serial;
3275   message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
3276                                           "/org/freedesktop/TestSuite",
3277                                           "org.freedesktop.DBus.Peer",
3278                                           "Ping");
3279 
3280   if (message == NULL)
3281     return TRUE;
3282 
3283   if (!dbus_connection_send (connection, message, &serial))
3284     {
3285       dbus_message_unref (message);
3286       return TRUE;
3287     }
3288 
3289   dbus_message_unref (message);
3290   message = NULL;
3291 
3292   bus_test_run_everything (context);
3293 
3294   /* Note: if this test is run in OOM mode, it will block when the bus
3295    * doesn't send a reply due to OOM.
3296    */
3297   block_connection_until_message_from_bus (context, connection, "reply from running Ping");
3298 
3299   message = pop_message_waiting_for_memory (connection);
3300   if (message == NULL)
3301     {
3302       _dbus_warn ("Failed to pop message! Should have been reply from Ping message");
3303       return FALSE;
3304     }
3305 
3306   if (dbus_message_get_reply_serial (message) != serial)
3307     {
3308       _dbus_warn ("Wrong reply serial");
3309       dbus_message_unref (message);
3310       return FALSE;
3311     }
3312 
3313   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
3314     {
3315       _dbus_warn ("Unexpected message return during Ping");
3316       dbus_message_unref (message);
3317       return FALSE;
3318     }
3319 
3320   dbus_message_unref (message);
3321   message = NULL;
3322 
3323   return TRUE;
3324 }
3325 
3326 /* returns TRUE if the correct thing happens,
3327  * but the correct thing may include OOM errors.
3328  */
3329 static dbus_bool_t
check_existent_get_machine_id(BusContext * context,DBusConnection * connection)3330 check_existent_get_machine_id (BusContext     *context,
3331                                DBusConnection *connection)
3332 {
3333   DBusError error = DBUS_ERROR_INIT;
3334   DBusMessage *message;
3335   dbus_uint32_t serial;
3336   DBusGUID uuid;
3337   const char *machine_id;
3338 
3339   if (!_dbus_read_local_machine_uuid (&uuid, FALSE, &error))
3340     {
3341       /* Unable to test further: either we ran out of memory, or neither
3342        * dbus nor systemd was ever correctly installed on this machine */
3343       _dbus_verbose ("Machine UUID not available: %s", error.message);
3344       dbus_error_free (&error);
3345       return TRUE;
3346     }
3347 
3348   message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
3349                                           "/org/freedesktop/TestSuite",
3350                                           "org.freedesktop.DBus.Peer",
3351                                           "GetMachineId");
3352 
3353   if (message == NULL)
3354     return TRUE;
3355 
3356   if (!dbus_connection_send (connection, message, &serial))
3357     {
3358       dbus_message_unref (message);
3359       return TRUE;
3360     }
3361 
3362   dbus_message_unref (message);
3363   message = NULL;
3364 
3365   bus_test_run_everything (context);
3366 
3367   /* Note: if this test is run in OOM mode, it will block when the bus
3368    * doesn't send a reply due to OOM.
3369    */
3370   block_connection_until_message_from_bus (context, connection, "reply from running GetMachineId");
3371 
3372   message = pop_message_waiting_for_memory (connection);
3373   if (message == NULL)
3374     {
3375       _dbus_warn ("Failed to pop message! Should have been reply from GetMachineId message");
3376       return FALSE;
3377     }
3378 
3379   if (dbus_message_get_reply_serial (message) != serial)
3380     {
3381       _dbus_warn ("Wrong reply serial");
3382       dbus_message_unref (message);
3383       return FALSE;
3384     }
3385 
3386   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
3387     {
3388       _dbus_warn ("Unexpected message return during GetMachineId");
3389       dbus_message_unref (message);
3390       return FALSE;
3391     }
3392 
3393   machine_id = NULL;
3394   if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &machine_id, DBUS_TYPE_INVALID))
3395     {
3396       _dbus_warn ("Did not get a machine ID in reply to GetMachineId");
3397       dbus_message_unref (message);
3398       return FALSE;
3399     }
3400 
3401   if (machine_id == NULL || strlen (machine_id) != 32)
3402     {
3403       _dbus_warn ("Machine id looks bogus: '%s'", machine_id ? machine_id : "null");
3404       dbus_message_unref (message);
3405       return FALSE;
3406     }
3407 
3408   /* We can't check that the machine id is correct because during make check it is
3409    * just made up for each process separately
3410    */
3411 
3412   dbus_message_unref (message);
3413   message = NULL;
3414 
3415   return TRUE;
3416 }
3417 
3418 /* returns TRUE if the correct thing happens,
3419  * but the correct thing may include OOM errors.
3420  */
3421 static dbus_bool_t
check_existent_service_auto_start(BusContext * context,DBusConnection * connection)3422 check_existent_service_auto_start (BusContext     *context,
3423                                    DBusConnection *connection)
3424 {
3425   DBusMessage *message;
3426   DBusMessage *base_service_message;
3427   dbus_uint32_t serial;
3428   dbus_bool_t retval;
3429   const char *base_service;
3430   const char *text;
3431 
3432   base_service_message = NULL;
3433 
3434   message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
3435                                           "/org/freedesktop/TestSuite",
3436                                           "org.freedesktop.TestSuite",
3437                                           "Echo");
3438 
3439   if (message == NULL)
3440     return TRUE;
3441 
3442   text = TEST_ECHO_MESSAGE;
3443   if (!dbus_message_append_args (message,
3444                                  DBUS_TYPE_STRING, &text,
3445                                  DBUS_TYPE_INVALID))
3446     {
3447       dbus_message_unref (message);
3448       return TRUE;
3449     }
3450 
3451   if (!dbus_connection_send (connection, message, &serial))
3452     {
3453       dbus_message_unref (message);
3454       return TRUE;
3455     }
3456 
3457   dbus_message_unref (message);
3458   message = NULL;
3459 
3460   bus_test_run_everything (context);
3461 
3462   /* now wait for the message bus to hear back from the activated
3463    * service.
3464    */
3465   block_connection_until_message_from_bus (context, connection, "reply to Echo on existent service");
3466   bus_test_run_everything (context);
3467 
3468   if (!dbus_connection_get_is_connected (connection))
3469     {
3470       _dbus_verbose ("connection was disconnected\n");
3471       return TRUE;
3472     }
3473 
3474   retval = FALSE;
3475 
3476   message = pop_message_waiting_for_memory (connection);
3477   if (message == NULL)
3478     {
3479       _dbus_warn ("Did not receive any messages after auto start %d on %p",
3480                   serial, connection);
3481       goto out;
3482     }
3483 
3484   verbose_message_received (connection, message);
3485   _dbus_verbose ("  (after sending %s)\n", "auto start");
3486 
3487   /* we should get zero or two ServiceOwnerChanged signals */
3488   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL)
3489     {
3490       GotServiceInfo message_kind;
3491 
3492       if (!check_base_service_activated (context, connection,
3493                                          message, &base_service))
3494         goto out;
3495 
3496       base_service_message = message;
3497       message = NULL;
3498 
3499       /* We may need to block here for the test service to exit or finish up */
3500       block_connection_until_message_from_bus (context, connection, "service to exit");
3501 
3502       /* Should get a service creation notification for the activated
3503        * service name, or a service deletion on the base service name
3504        */
3505       message = dbus_connection_borrow_message (connection);
3506       if (message == NULL)
3507         {
3508           _dbus_warn ("No message after auto activation "
3509                       "(should be a service announcement)");
3510           dbus_connection_return_message (connection, message);
3511           message = NULL;
3512           goto out;
3513         }
3514 
3515       message_kind = check_got_service_info (message);
3516 
3517       dbus_connection_return_message (connection, message);
3518       message = NULL;
3519 
3520       switch (message_kind)
3521         {
3522         case GOT_SERVICE_CREATED:
3523           message = pop_message_waiting_for_memory (connection);
3524           if (message == NULL)
3525             {
3526               _dbus_warn ("Failed to pop message we just put back! "
3527                           "should have been a NameOwnerChanged (creation)");
3528               goto out;
3529             }
3530 
3531           /* Check that ServiceOwnerChanged (creation) was correctly received */
3532           if (!check_service_auto_activated (context, connection, EXISTENT_SERVICE_NAME,
3533                                              base_service, message))
3534             goto out;
3535 
3536           dbus_message_unref (message);
3537           message = NULL;
3538 
3539           break;
3540 
3541         case GOT_SERVICE_DELETED:
3542           {
3543             /* The service started up and got a base address, but then
3544              * failed to register under EXISTENT_SERVICE_NAME
3545              */
3546             CheckServiceOwnerChangedData socd;
3547 
3548             socd.expected_kind = SERVICE_DELETED;
3549             socd.expected_service_name = base_service;
3550             socd.failed = FALSE;
3551             socd.skip_connection = NULL;
3552             socd.context = context;
3553 
3554             bus_test_clients_foreach (check_service_owner_changed_foreach,
3555                                       &socd);
3556 
3557             if (socd.failed)
3558               goto out;
3559 
3560             break;
3561           }
3562 
3563         case GOT_ERROR:
3564         case GOT_SOMETHING_ELSE:
3565         default:
3566           _dbus_warn ("Unexpected message after auto activation");
3567           goto out;
3568         }
3569     }
3570 
3571   /* OK, now we've dealt with ServiceOwnerChanged signals, now should
3572    * come the method reply (or error) from the initial method call
3573    */
3574 
3575   /* Note: if this test is run in OOM mode, it will block when the bus
3576    * doesn't send a reply due to OOM.
3577    */
3578   block_connection_until_message_from_bus (context, connection, "reply from echo message after auto-activation");
3579 
3580   message = pop_message_waiting_for_memory (connection);
3581   if (message == NULL)
3582     {
3583       _dbus_warn ("Failed to pop message! Should have been reply from echo message");
3584       goto out;
3585     }
3586 
3587   if (dbus_message_get_reply_serial (message) != serial)
3588     {
3589       _dbus_warn ("Wrong reply serial");
3590       goto out;
3591     }
3592 
3593   dbus_message_unref (message);
3594   message = NULL;
3595 
3596   if (!check_existent_ping (context, connection))
3597     goto out;
3598 
3599   if (!check_existent_get_machine_id (context, connection))
3600     goto out;
3601 
3602   if (!check_existent_hello_from_self (context, connection))
3603     goto out;
3604 
3605   if (!check_send_exit_to_service (context, connection,
3606                                    EXISTENT_SERVICE_NAME,
3607                                    base_service))
3608     goto out;
3609 
3610   retval = TRUE;
3611 
3612  out:
3613   if (message)
3614     dbus_message_unref (message);
3615 
3616   if (base_service_message)
3617     dbus_message_unref (base_service_message);
3618 
3619   return retval;
3620 }
3621 
3622 #define SERVICE_FILE_MISSING_NAME "org.freedesktop.DBus.TestSuiteEchoServiceDotServiceFileDoesNotExist"
3623 
3624 /* returns TRUE if the correct thing happens,
3625  * but the correct thing may include OOM errors.
3626  */
3627 static dbus_bool_t
check_launch_service_file_missing(BusContext * context,DBusConnection * connection)3628 check_launch_service_file_missing (BusContext     *context,
3629                                    DBusConnection *connection)
3630 {
3631   DBusMessage *message;
3632   dbus_uint32_t serial;
3633   dbus_bool_t retval;
3634 
3635   message = dbus_message_new_method_call (SERVICE_FILE_MISSING_NAME,
3636                                           "/org/freedesktop/TestSuite",
3637                                           "org.freedesktop.TestSuite",
3638                                           "Echo");
3639 
3640   if (message == NULL)
3641     return TRUE;
3642 
3643   if (!dbus_connection_send (connection, message, &serial))
3644     {
3645       dbus_message_unref (message);
3646       return TRUE;
3647     }
3648 
3649   dbus_message_unref (message);
3650   message = NULL;
3651 
3652   bus_test_run_everything (context);
3653   block_connection_until_message_from_bus (context, connection, "reply to service file missing should fail to auto-start");
3654   bus_test_run_everything (context);
3655 
3656   if (!dbus_connection_get_is_connected (connection))
3657     {
3658       _dbus_verbose ("connection was disconnected\n");
3659       return TRUE;
3660     }
3661 
3662   retval = FALSE;
3663 
3664   message = pop_message_waiting_for_memory (connection);
3665   if (message == NULL)
3666     {
3667       _dbus_warn ("Did not receive a reply to %s %d on %p",
3668                   "Echo message (auto activation)", serial, connection);
3669       goto out;
3670     }
3671 
3672   verbose_message_received (connection, message);
3673 
3674   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
3675     {
3676       if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
3677         {
3678           _dbus_warn ("Message has wrong sender %s",
3679                       dbus_message_get_sender (message) ?
3680                       dbus_message_get_sender (message) : "(none)");
3681           goto out;
3682         }
3683 
3684       if (dbus_message_is_error (message,
3685                                  DBUS_ERROR_NO_MEMORY))
3686         {
3687           ; /* good, this is a valid response */
3688         }
3689       else if (dbus_message_is_error (message,
3690                                       DBUS_ERROR_SERVICE_UNKNOWN))
3691         {
3692           _dbus_verbose("got service unknown\n");
3693           ; /* good, this is expected (only valid when using launch helper) */
3694         }
3695       else
3696         {
3697           warn_unexpected (connection, message, "not this error");
3698 
3699           goto out;
3700         }
3701     }
3702   else
3703     {
3704       _dbus_warn ("Did not expect to successfully auto-start missing service");
3705       goto out;
3706     }
3707 
3708   retval = TRUE;
3709 
3710  out:
3711   if (message)
3712     dbus_message_unref (message);
3713 
3714   return retval;
3715 }
3716 
3717 #ifndef DBUS_WIN
3718 
3719 #define SERVICE_USER_MISSING_NAME "org.freedesktop.DBus.TestSuiteNoUser"
3720 
3721 /* returns TRUE if the correct thing happens,
3722  * but the correct thing may include OOM errors.
3723  */
3724 static dbus_bool_t
check_launch_service_user_missing(BusContext * context,DBusConnection * connection)3725 check_launch_service_user_missing (BusContext     *context,
3726                                    DBusConnection *connection)
3727 {
3728   DBusMessage *message;
3729   dbus_uint32_t serial;
3730   dbus_bool_t retval;
3731 
3732   message = dbus_message_new_method_call (SERVICE_USER_MISSING_NAME,
3733                                           "/org/freedesktop/TestSuite",
3734                                           "org.freedesktop.TestSuite",
3735                                           "Echo");
3736 
3737   if (message == NULL)
3738     return TRUE;
3739 
3740   if (!dbus_connection_send (connection, message, &serial))
3741     {
3742       dbus_message_unref (message);
3743       return TRUE;
3744     }
3745 
3746   dbus_message_unref (message);
3747   message = NULL;
3748 
3749   bus_test_run_everything (context);
3750   block_connection_until_message_from_bus (context, connection,
3751   					   "reply to service which should fail to auto-start (missing User)");
3752   bus_test_run_everything (context);
3753 
3754   if (!dbus_connection_get_is_connected (connection))
3755     {
3756       _dbus_warn ("connection was disconnected");
3757       return TRUE;
3758     }
3759 
3760   retval = FALSE;
3761 
3762   message = pop_message_waiting_for_memory (connection);
3763   if (message == NULL)
3764     {
3765       _dbus_warn ("Did not receive a reply to %s %d on %p",
3766                   "Echo message (auto activation)", serial, connection);
3767       goto out;
3768     }
3769 
3770   verbose_message_received (connection, message);
3771 
3772   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
3773     {
3774       if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
3775         {
3776           _dbus_warn ("Message has wrong sender %s",
3777                       dbus_message_get_sender (message) ?
3778                       dbus_message_get_sender (message) : "(none)");
3779           goto out;
3780         }
3781 
3782       if (dbus_message_is_error (message,
3783                                  DBUS_ERROR_NO_MEMORY))
3784         {
3785           ; /* good, this is a valid response */
3786         }
3787       else if (dbus_message_is_error (message,
3788                                       DBUS_ERROR_SPAWN_FILE_INVALID))
3789         {
3790           _dbus_verbose("got service file invalid\n");
3791           ; /* good, this is expected (only valid when using launch helper) */
3792         }
3793       else
3794         {
3795           warn_unexpected (connection, message, "not this error");
3796 
3797           goto out;
3798         }
3799     }
3800   else
3801     {
3802       _dbus_warn ("Did not expect to successfully auto-start missing service");
3803       goto out;
3804     }
3805 
3806   retval = TRUE;
3807 
3808  out:
3809   if (message)
3810     dbus_message_unref (message);
3811 
3812   return retval;
3813 }
3814 
3815 #define SERVICE_EXEC_MISSING_NAME "org.freedesktop.DBus.TestSuiteNoExec"
3816 
3817 /* returns TRUE if the correct thing happens,
3818  * but the correct thing may include OOM errors.
3819  */
3820 static dbus_bool_t
check_launch_service_exec_missing(BusContext * context,DBusConnection * connection)3821 check_launch_service_exec_missing (BusContext     *context,
3822                                    DBusConnection *connection)
3823 {
3824   DBusMessage *message;
3825   dbus_uint32_t serial;
3826   dbus_bool_t retval;
3827 
3828   message = dbus_message_new_method_call (SERVICE_EXEC_MISSING_NAME,
3829                                           "/org/freedesktop/TestSuite",
3830                                           "org.freedesktop.TestSuite",
3831                                           "Echo");
3832 
3833   if (message == NULL)
3834     return TRUE;
3835 
3836   if (!dbus_connection_send (connection, message, &serial))
3837     {
3838       dbus_message_unref (message);
3839       return TRUE;
3840     }
3841 
3842   dbus_message_unref (message);
3843   message = NULL;
3844 
3845   bus_test_run_everything (context);
3846   block_connection_until_message_from_bus (context, connection,
3847   					   "reply to service which should fail to auto-start (missing Exec)");
3848   bus_test_run_everything (context);
3849 
3850   if (!dbus_connection_get_is_connected (connection))
3851     {
3852       _dbus_warn ("connection was disconnected");
3853       return TRUE;
3854     }
3855 
3856   retval = FALSE;
3857 
3858   message = pop_message_waiting_for_memory (connection);
3859   if (message == NULL)
3860     {
3861       _dbus_warn ("Did not receive a reply to %s %d on %p",
3862                   "Echo message (auto activation)", serial, connection);
3863       goto out;
3864     }
3865 
3866   verbose_message_received (connection, message);
3867 
3868   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
3869     {
3870       if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
3871         {
3872           _dbus_warn ("Message has wrong sender %s",
3873                       dbus_message_get_sender (message) ?
3874                       dbus_message_get_sender (message) : "(none)");
3875           goto out;
3876         }
3877 
3878       if (dbus_message_is_error (message,
3879                                  DBUS_ERROR_NO_MEMORY))
3880         {
3881           ; /* good, this is a valid response */
3882         }
3883       else if (dbus_message_is_error (message,
3884                                       DBUS_ERROR_SERVICE_UNKNOWN))
3885         {
3886           _dbus_verbose("could not activate as invalid service file was not added\n");
3887           ; /* good, this is expected as we shouldn't have been added to
3888              * the activation list with a missing Exec key */
3889         }
3890       else if (dbus_message_is_error (message,
3891                                       DBUS_ERROR_SPAWN_FILE_INVALID))
3892         {
3893           _dbus_verbose("got service file invalid\n");
3894           ; /* good, this is allowed, and is the message passed back from the
3895              * launch helper */
3896         }
3897       else
3898         {
3899           warn_unexpected (connection, message, "not this error");
3900 
3901           goto out;
3902         }
3903     }
3904   else
3905     {
3906       _dbus_warn ("Did not expect to successfully auto-start missing service");
3907       goto out;
3908     }
3909 
3910   retval = TRUE;
3911 
3912  out:
3913   if (message)
3914     dbus_message_unref (message);
3915 
3916   return retval;
3917 }
3918 
3919 #define SERVICE_SERVICE_MISSING_NAME "org.freedesktop.DBus.TestSuiteNoService"
3920 
3921 /* returns TRUE if the correct thing happens,
3922  * but the correct thing may include OOM errors.
3923  */
3924 static dbus_bool_t
check_launch_service_service_missing(BusContext * context,DBusConnection * connection)3925 check_launch_service_service_missing (BusContext     *context,
3926                                       DBusConnection *connection)
3927 {
3928   DBusMessage *message;
3929   dbus_uint32_t serial;
3930   dbus_bool_t retval;
3931 
3932   message = dbus_message_new_method_call (SERVICE_SERVICE_MISSING_NAME,
3933                                           "/org/freedesktop/TestSuite",
3934                                           "org.freedesktop.TestSuite",
3935                                           "Echo");
3936 
3937   if (message == NULL)
3938     return TRUE;
3939 
3940   if (!dbus_connection_send (connection, message, &serial))
3941     {
3942       dbus_message_unref (message);
3943       return TRUE;
3944     }
3945 
3946   dbus_message_unref (message);
3947   message = NULL;
3948 
3949   bus_test_run_everything (context);
3950   block_connection_until_message_from_bus (context, connection,
3951   					   "reply to service which should fail to auto-start (missing Service)");
3952   bus_test_run_everything (context);
3953 
3954   if (!dbus_connection_get_is_connected (connection))
3955     {
3956       _dbus_warn ("connection was disconnected");
3957       return TRUE;
3958     }
3959 
3960   retval = FALSE;
3961 
3962   message = pop_message_waiting_for_memory (connection);
3963   if (message == NULL)
3964     {
3965       _dbus_warn ("Did not receive a reply to %s %d on %p",
3966                   "Echo message (auto activation)", serial, connection);
3967       goto out;
3968     }
3969 
3970   verbose_message_received (connection, message);
3971 
3972   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
3973     {
3974       if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
3975         {
3976           _dbus_warn ("Message has wrong sender %s",
3977                       dbus_message_get_sender (message) ?
3978                       dbus_message_get_sender (message) : "(none)");
3979           goto out;
3980         }
3981 
3982       if (dbus_message_is_error (message,
3983                                  DBUS_ERROR_NO_MEMORY))
3984         {
3985           ; /* good, this is a valid response */
3986         }
3987       else if (dbus_message_is_error (message,
3988                                       DBUS_ERROR_SERVICE_UNKNOWN))
3989         {
3990           _dbus_verbose("could not activate as invalid service file was not added\n");
3991           ; /* good, this is expected as we shouldn't have been added to
3992              * the activation list with a missing Exec key */
3993         }
3994       else if (dbus_message_is_error (message,
3995                                       DBUS_ERROR_SPAWN_FILE_INVALID))
3996         {
3997           _dbus_verbose("got service file invalid\n");
3998           ; /* good, this is allowed, and is the message passed back from the
3999              * launch helper */
4000         }
4001       else
4002         {
4003           warn_unexpected (connection, message, "not this error");
4004 
4005           goto out;
4006         }
4007     }
4008   else
4009     {
4010       _dbus_warn ("Did not expect to successfully auto-start missing service");
4011       goto out;
4012     }
4013 
4014   retval = TRUE;
4015 
4016  out:
4017   if (message)
4018     dbus_message_unref (message);
4019 
4020   return retval;
4021 }
4022 #endif
4023 
4024 #define SHELL_FAIL_SERVICE_NAME "org.freedesktop.DBus.TestSuiteShellEchoServiceFail"
4025 
4026 /* returns TRUE if the correct thing happens,
4027  * but the correct thing may include OOM errors.
4028  */
4029 static dbus_bool_t
check_shell_fail_service_auto_start(BusContext * context,DBusConnection * connection)4030 check_shell_fail_service_auto_start (BusContext     *context,
4031                                      DBusConnection *connection)
4032 {
4033   DBusMessage *message;
4034   dbus_uint32_t serial;
4035   dbus_bool_t retval;
4036 
4037   message = dbus_message_new_method_call (SHELL_FAIL_SERVICE_NAME,
4038                                           "/org/freedesktop/TestSuite",
4039                                           "org.freedesktop.TestSuite",
4040                                           "Echo");
4041 
4042   if (message == NULL)
4043     return TRUE;
4044 
4045   if (!dbus_connection_send (connection, message, &serial))
4046     {
4047       dbus_message_unref (message);
4048       return TRUE;
4049     }
4050 
4051   dbus_message_unref (message);
4052   message = NULL;
4053 
4054   bus_test_run_everything (context);
4055   block_connection_until_message_from_bus (context, connection, "reply to shell Echo on service which should fail to auto-start");
4056   bus_test_run_everything (context);
4057 
4058   if (!dbus_connection_get_is_connected (connection))
4059     {
4060       _dbus_verbose ("connection was disconnected\n");
4061       return TRUE;
4062     }
4063 
4064   retval = FALSE;
4065 
4066   message = pop_message_waiting_for_memory (connection);
4067   if (message == NULL)
4068     {
4069       _dbus_warn ("Did not receive a reply to %s %d on %p",
4070                   "Echo message (auto activation)", serial, connection);
4071       goto out;
4072     }
4073 
4074   verbose_message_received (connection, message);
4075 
4076   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
4077     {
4078       if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
4079         {
4080           _dbus_warn ("Message has wrong sender %s",
4081                       dbus_message_get_sender (message) ?
4082                       dbus_message_get_sender (message) : "(none)");
4083           goto out;
4084         }
4085 
4086       if (dbus_message_is_error (message,
4087                                  DBUS_ERROR_NO_MEMORY))
4088         {
4089           ; /* good, this is a valid response */
4090         }
4091       else if (dbus_message_is_error (message,
4092                                       DBUS_ERROR_INVALID_ARGS))
4093         {
4094           _dbus_verbose("got invalid args\n");
4095           ; /* good, this is expected also */
4096         }
4097       else
4098         {
4099           warn_unexpected (connection, message, "not this error");
4100 
4101           goto out;
4102         }
4103     }
4104   else
4105     {
4106       _dbus_warn ("Did not expect to successfully auto-start shell fail service");
4107       goto out;
4108     }
4109 
4110   retval = TRUE;
4111 
4112  out:
4113   if (message)
4114     dbus_message_unref (message);
4115 
4116   return retval;
4117 }
4118 
4119 #define SHELL_SUCCESS_SERVICE_NAME "org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess"
4120 
4121 /* returns TRUE if the correct thing happens,
4122  * but the correct thing may include OOM errors.
4123  */
4124 static dbus_bool_t
check_shell_service_success_auto_start(BusContext * context,DBusConnection * connection)4125 check_shell_service_success_auto_start (BusContext     *context,
4126                                         DBusConnection *connection)
4127 {
4128   DBusMessage *message;
4129   DBusMessage *base_service_message;
4130   dbus_uint32_t serial;
4131   dbus_bool_t retval;
4132   const char *base_service;
4133   const char *argv[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
4134 
4135   base_service_message = NULL;
4136 
4137   message = dbus_message_new_method_call (SHELL_SUCCESS_SERVICE_NAME,
4138                                           "/org/freedesktop/TestSuite",
4139                                           "org.freedesktop.TestSuite",
4140                                           "Echo");
4141 
4142   if (message == NULL)
4143     return TRUE;
4144 
4145   if (!dbus_connection_send (connection, message, &serial))
4146     {
4147       dbus_message_unref (message);
4148       return TRUE;
4149     }
4150 
4151   dbus_message_unref (message);
4152   message = NULL;
4153 
4154   bus_test_run_everything (context);
4155 
4156   /* now wait for the message bus to hear back from the activated
4157    * service.
4158    */
4159   block_connection_until_message_from_bus (context, connection, "reply to Echo on shell success service");
4160   bus_test_run_everything (context);
4161 
4162   if (!dbus_connection_get_is_connected (connection))
4163     {
4164       _dbus_verbose ("connection was disconnected\n");
4165       return TRUE;
4166     }
4167 
4168   retval = FALSE;
4169 
4170   message = pop_message_waiting_for_memory (connection);
4171   if (message == NULL)
4172     {
4173       _dbus_warn ("Did not receive any messages after auto start %d on %p",
4174                   serial, connection);
4175       goto out;
4176     }
4177 
4178   verbose_message_received (connection, message);
4179   _dbus_verbose ("  (after sending %s)\n", "auto start");
4180 
4181   /* we should get zero or two ServiceOwnerChanged signals */
4182   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL)
4183     {
4184       GotServiceInfo message_kind;
4185 
4186       if (!check_base_service_activated (context, connection,
4187                                          message, &base_service))
4188         goto out;
4189 
4190       base_service_message = message;
4191       message = NULL;
4192 
4193       /* We may need to block here for the test service to exit or finish up */
4194       block_connection_until_message_from_bus (context, connection, "service to exit");
4195 
4196       /* Should get a service creation notification for the activated
4197        * service name, or a service deletion on the base service name
4198        */
4199       message = dbus_connection_borrow_message (connection);
4200       if (message == NULL)
4201         {
4202           _dbus_warn ("No message after auto activation "
4203                       "(should be a service announcement)");
4204           dbus_connection_return_message (connection, message);
4205           message = NULL;
4206           goto out;
4207         }
4208 
4209       message_kind = check_got_service_info (message);
4210 
4211       dbus_connection_return_message (connection, message);
4212       message = NULL;
4213 
4214       switch (message_kind)
4215         {
4216         case GOT_SERVICE_CREATED:
4217           message = pop_message_waiting_for_memory (connection);
4218           if (message == NULL)
4219             {
4220               _dbus_warn ("Failed to pop message we just put back! "
4221                           "should have been a NameOwnerChanged (creation)");
4222               goto out;
4223             }
4224 
4225           /* Check that ServiceOwnerChanged (creation) was correctly received */
4226           if (!check_service_auto_activated (context, connection, SHELL_SUCCESS_SERVICE_NAME,
4227                                              base_service, message))
4228             goto out;
4229 
4230           dbus_message_unref (message);
4231           message = NULL;
4232 
4233           break;
4234 
4235         case GOT_SERVICE_DELETED:
4236           {
4237             /* The service started up and got a base address, but then
4238              * failed to register under SHELL_SUCCESS_SERVICE_NAME
4239              */
4240             CheckServiceOwnerChangedData socd;
4241 
4242             socd.expected_kind = SERVICE_DELETED;
4243             socd.expected_service_name = base_service;
4244             socd.failed = FALSE;
4245             socd.skip_connection = NULL;
4246             socd.context = context;
4247 
4248             bus_test_clients_foreach (check_service_owner_changed_foreach,
4249                                       &socd);
4250 
4251             if (socd.failed)
4252               goto out;
4253 
4254             break;
4255           }
4256 
4257         case GOT_ERROR:
4258         case GOT_SOMETHING_ELSE:
4259         default:
4260           _dbus_warn ("Unexpected message after auto activation");
4261           goto out;
4262         }
4263     }
4264 
4265   /* OK, now we've dealt with ServiceOwnerChanged signals, now should
4266    * come the method reply (or error) from the initial method call
4267    */
4268 
4269   /* Note: if this test is run in OOM mode, it will block when the bus
4270    * doesn't send a reply due to OOM.
4271    */
4272   block_connection_until_message_from_bus (context, connection, "reply from echo message after auto-activation");
4273 
4274   message = pop_message_waiting_for_memory (connection);
4275   if (message == NULL)
4276     {
4277       _dbus_warn ("Failed to pop message! Should have been reply from echo message");
4278       goto out;
4279     }
4280 
4281   if (dbus_message_get_reply_serial (message) != serial)
4282     {
4283       _dbus_warn ("Wrong reply serial");
4284       goto out;
4285     }
4286 
4287   if (!dbus_message_get_args (message, NULL,
4288                                        DBUS_TYPE_STRING, &argv[0],
4289                                        DBUS_TYPE_STRING, &argv[1],
4290                                        DBUS_TYPE_STRING, &argv[2],
4291                                        DBUS_TYPE_STRING, &argv[3],
4292                                        DBUS_TYPE_STRING, &argv[4],
4293                                        DBUS_TYPE_STRING, &argv[5],
4294                                        DBUS_TYPE_STRING, &argv[6],
4295                                        DBUS_TYPE_INVALID))
4296     {
4297       _dbus_warn ("Error getting arguments from return");
4298       goto out;
4299     }
4300 
4301    /* don't worry about arg[0] as it may be different
4302       depending on the path to the tests
4303    */
4304   if (strcmp("-test", argv[1]) != 0)
4305     {
4306       _dbus_warn ("Unexpected argv[1] in shell success service test (expected: %s, got: %s)",
4307                   "-test", argv[1]);
4308       goto out;
4309     }
4310 
4311   if (strcmp("that", argv[2]) != 0)
4312     {
4313       _dbus_warn ("Unexpected argv[2] in shell success service test (expected: %s, got: %s)",
4314                    "that", argv[2]);
4315       goto out;
4316     }
4317 
4318   if (strcmp("we get", argv[3]) != 0)
4319     {
4320       _dbus_warn ("Unexpected argv[3] in shell success service test (expected: %s, got: %s)",
4321                    "we get", argv[3]);
4322       goto out;
4323     }
4324 
4325   if (strcmp("back", argv[4]) != 0)
4326     {
4327       _dbus_warn ("Unexpected argv[4] in shell success service test (expected: %s, got: %s)",
4328                    "back", argv[4]);
4329       goto out;
4330     }
4331 
4332   if (strcmp("--what", argv[5]) != 0)
4333     {
4334       _dbus_warn ("Unexpected argv[5] in shell success service test (expected: %s, got: %s)",
4335                    "--what", argv[5]);
4336       goto out;
4337     }
4338 
4339   if (strcmp("we put in", argv[6]) != 0)
4340     {
4341       _dbus_warn ("Unexpected argv[6] in shell success service test (expected: %s, got: %s)",
4342                    "we put in", argv[6]);
4343       goto out;
4344     }
4345 
4346   dbus_message_unref (message);
4347   message = NULL;
4348 
4349   if (!check_send_exit_to_service (context, connection,
4350                                    SHELL_SUCCESS_SERVICE_NAME,
4351                                    base_service))
4352     goto out;
4353 
4354   retval = TRUE;
4355 
4356  out:
4357   if (message)
4358     dbus_message_unref (message);
4359 
4360   if (base_service_message)
4361     dbus_message_unref (base_service_message);
4362 
4363   return retval;
4364 }
4365 
4366 typedef struct
4367 {
4368   Check1Func func;
4369   BusContext *context;
4370 } Check1Data;
4371 
4372 static dbus_bool_t
check_oom_check1_func(void * data)4373 check_oom_check1_func (void *data)
4374 {
4375   Check1Data *d = data;
4376 
4377   if (! (* d->func) (d->context))
4378     return FALSE;
4379 
4380   if (!check_no_leftovers (d->context))
4381     {
4382       _dbus_warn ("Messages were left over, should be covered by test suite");
4383       return FALSE;
4384     }
4385 
4386   return TRUE;
4387 }
4388 
4389 static void
check1_try_iterations(BusContext * context,const char * description,Check1Func func)4390 check1_try_iterations (BusContext *context,
4391                        const char *description,
4392                        Check1Func  func)
4393 {
4394   Check1Data d;
4395 
4396   d.func = func;
4397   d.context = context;
4398 
4399   if (!_dbus_test_oom_handling (description, check_oom_check1_func,
4400                                 &d))
4401     _dbus_assert_not_reached ("test failed");
4402 }
4403 
4404 static dbus_bool_t
check_get_services(BusContext * context,DBusConnection * connection,const char * method,char *** services,int * len)4405 check_get_services (BusContext     *context,
4406 		    DBusConnection *connection,
4407 		    const char     *method,
4408 		    char         ***services,
4409 		    int            *len)
4410 {
4411   DBusMessage *message;
4412   dbus_uint32_t serial;
4413   dbus_bool_t retval;
4414   DBusError error;
4415   char **srvs;
4416   int l;
4417 
4418   retval = FALSE;
4419   dbus_error_init (&error);
4420   message = NULL;
4421 
4422   message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
4423 					  DBUS_PATH_DBUS,
4424 					  DBUS_INTERFACE_DBUS,
4425 					  method);
4426 
4427   if (message == NULL)
4428     return TRUE;
4429 
4430   if (!dbus_connection_send (connection, message, &serial))
4431     {
4432       dbus_message_unref (message);
4433       return TRUE;
4434     }
4435 
4436   /* send our message */
4437   bus_test_run_clients_loop (SEND_PENDING (connection));
4438 
4439   dbus_message_unref (message);
4440   message = NULL;
4441 
4442   dbus_connection_ref (connection); /* because we may get disconnected */
4443   block_connection_until_message_from_bus (context, connection, "reply to ListActivatableNames/ListNames");
4444 
4445   if (!dbus_connection_get_is_connected (connection))
4446     {
4447       _dbus_verbose ("connection was disconnected\n");
4448 
4449       dbus_connection_unref (connection);
4450 
4451       return TRUE;
4452     }
4453 
4454   dbus_connection_unref (connection);
4455 
4456   message = pop_message_waiting_for_memory (connection);
4457   if (message == NULL)
4458     {
4459       _dbus_warn ("Did not receive a reply to %s %d on %p",
4460 		  method, serial, connection);
4461       goto out;
4462     }
4463 
4464   verbose_message_received (connection, message);
4465 
4466   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
4467     {
4468       if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY))
4469 	{
4470 	  ; /* good, this is a valid response */
4471 	}
4472       else
4473 	{
4474 	  warn_unexpected (connection, message, "not this error");
4475 
4476 	  goto out;
4477 	}
4478     }
4479   else
4480     {
4481       if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
4482 	{
4483 	  ; /* good, expected */
4484 	}
4485       else
4486 	{
4487 	  warn_unexpected (connection, message,
4488 			   "method_return for ListActivatableNames/ListNames");
4489 
4490 	  goto out;
4491 	}
4492 
4493     retry_get_property:
4494 
4495       if (!dbus_message_get_args (message, &error,
4496 				  DBUS_TYPE_ARRAY,
4497 				  DBUS_TYPE_STRING,
4498 				  &srvs, &l,
4499 				  DBUS_TYPE_INVALID))
4500 	{
4501 	  if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
4502 	    {
4503 	      _dbus_verbose ("no memory to list services by %s\n", method);
4504 	      dbus_error_free (&error);
4505 	      _dbus_wait_for_memory ();
4506 	      goto retry_get_property;
4507 	    }
4508 	  else
4509 	    {
4510 	      _dbus_assert (dbus_error_is_set (&error));
4511 	      _dbus_warn ("Did not get the expected DBUS_TYPE_ARRAY from %s", method);
4512 	      goto out;
4513 	    }
4514 	} else {
4515 	  *services = srvs;
4516 	  *len = l;
4517 	}
4518     }
4519 
4520   if (!check_no_leftovers (context))
4521     goto out;
4522 
4523   retval = TRUE;
4524 
4525  out:
4526   dbus_error_free (&error);
4527 
4528   if (message)
4529     dbus_message_unref (message);
4530 
4531   return retval;
4532 }
4533 
4534 /* returns TRUE if the correct thing happens,
4535  * but the correct thing may include OOM errors.
4536  */
4537 static dbus_bool_t
check_list_services(BusContext * context,DBusConnection * connection)4538 check_list_services (BusContext     *context,
4539 		     DBusConnection *connection)
4540 {
4541   DBusMessage  *message;
4542   DBusMessage  *base_service_message;
4543   const char   *base_service;
4544   dbus_uint32_t serial;
4545   dbus_bool_t   retval;
4546   const char   *existent = EXISTENT_SERVICE_NAME;
4547   dbus_uint32_t flags;
4548   char        **services;
4549   int           len;
4550 
4551   _dbus_verbose ("check_list_services for %p\n", connection);
4552 
4553   if (!check_get_services (context, connection, "ListActivatableNames", &services, &len))
4554     {
4555       return TRUE;
4556     }
4557 
4558   if (!_dbus_string_array_contains ((const char **)services, existent))
4559     {
4560       _dbus_warn ("Did not get the expected %s from ListActivatableNames", existent);
4561       dbus_free_string_array (services);
4562       return FALSE;
4563     }
4564 
4565   dbus_free_string_array (services);
4566 
4567   base_service_message = NULL;
4568 
4569   message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
4570 					  DBUS_PATH_DBUS,
4571 					  DBUS_INTERFACE_DBUS,
4572 					  "StartServiceByName");
4573 
4574   if (message == NULL)
4575     return TRUE;
4576 
4577   dbus_message_set_auto_start (message, FALSE);
4578 
4579   flags = 0;
4580   if (!dbus_message_append_args (message,
4581 				 DBUS_TYPE_STRING, &existent,
4582 				 DBUS_TYPE_UINT32, &flags,
4583 				 DBUS_TYPE_INVALID))
4584     {
4585       dbus_message_unref (message);
4586       return TRUE;
4587     }
4588 
4589   if (!dbus_connection_send (connection, message, &serial))
4590     {
4591       dbus_message_unref (message);
4592       return TRUE;
4593     }
4594 
4595   dbus_message_unref (message);
4596   message = NULL;
4597 
4598   bus_test_run_everything (context);
4599 
4600   /* now wait for the message bus to hear back from the activated
4601    * service.
4602    */
4603   block_connection_until_message_from_bus (context, connection, "activated service to connect");
4604 
4605   bus_test_run_everything (context);
4606 
4607   if (!dbus_connection_get_is_connected (connection))
4608     {
4609       _dbus_verbose ("connection was disconnected\n");
4610       return TRUE;
4611     }
4612 
4613   retval = FALSE;
4614 
4615   message = pop_message_waiting_for_memory (connection);
4616   if (message == NULL)
4617     {
4618       _dbus_warn ("Did not receive any messages after %s %d on %p",
4619 		  "StartServiceByName", serial, connection);
4620       goto out;
4621     }
4622 
4623   verbose_message_received (connection, message);
4624   _dbus_verbose ("  (after sending %s)\n", "StartServiceByName");
4625 
4626   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
4627     {
4628       if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
4629 	{
4630 	  _dbus_warn ("Message has wrong sender %s",
4631 		      dbus_message_get_sender (message) ?
4632 		      dbus_message_get_sender (message) : "(none)");
4633 	  goto out;
4634 	}
4635 
4636       if (dbus_message_is_error (message,
4637 				 DBUS_ERROR_NO_MEMORY))
4638 	{
4639 	  ; /* good, this is a valid response */
4640 	}
4641       else if (dbus_message_is_error (message,
4642 				      DBUS_ERROR_SPAWN_CHILD_EXITED) ||
4643 	       dbus_message_is_error (message,
4644 				      DBUS_ERROR_SPAWN_CHILD_SIGNALED) ||
4645 	       dbus_message_is_error (message,
4646 				      DBUS_ERROR_SPAWN_EXEC_FAILED))
4647 	{
4648 	  ; /* good, this is expected also */
4649 	}
4650       else
4651 	{
4652 	  _dbus_warn ("Did not expect error %s",
4653 		      dbus_message_get_error_name (message));
4654 	  goto out;
4655 	}
4656     }
4657   else
4658     {
4659       GotServiceInfo message_kind;
4660 
4661       if (!check_base_service_activated (context, connection,
4662 					 message, &base_service))
4663 	goto out;
4664 
4665       base_service_message = message;
4666       message = NULL;
4667 
4668       /* We may need to block here for the test service to exit or finish up */
4669       block_connection_until_message_from_bus (context, connection, "test service to exit or finish up");
4670 
4671       message = dbus_connection_borrow_message (connection);
4672       if (message == NULL)
4673 	{
4674 	  _dbus_warn ("Did not receive any messages after base service creation notification");
4675 	  goto out;
4676 	}
4677 
4678       message_kind = check_got_service_info (message);
4679 
4680       dbus_connection_return_message (connection, message);
4681       message = NULL;
4682 
4683       switch (message_kind)
4684 	{
4685 	case GOT_SOMETHING_ELSE:
4686 	case GOT_ERROR:
4687 	case GOT_SERVICE_DELETED:
4688 	default:
4689 	  _dbus_warn ("Unexpected message after ActivateService "
4690 		      "(should be an error or a service announcement)");
4691 	  goto out;
4692 
4693 	case GOT_SERVICE_CREATED:
4694 	  message = pop_message_waiting_for_memory (connection);
4695 	  if (message == NULL)
4696 	    {
4697 	      _dbus_warn ("Failed to pop message we just put back! "
4698 			  "should have been a NameOwnerChanged (creation)");
4699 	      goto out;
4700 	    }
4701 
4702 	  if (!check_service_activated (context, connection, EXISTENT_SERVICE_NAME,
4703 					base_service, message))
4704 	    goto out;
4705 
4706 	  dbus_message_unref (message);
4707 	  message = NULL;
4708 
4709 	  if (!check_no_leftovers (context))
4710 	    {
4711 	      _dbus_warn ("Messages were left over after successful activation");
4712 	      goto out;
4713 	    }
4714 
4715 	  break;
4716 	}
4717     }
4718 
4719   if (!check_get_services (context, connection, "ListNames", &services, &len))
4720     {
4721       return TRUE;
4722     }
4723 
4724   if (!_dbus_string_array_contains ((const char **)services, existent))
4725     {
4726       _dbus_warn ("Did not get the expected %s from ListNames", existent);
4727       goto out;
4728     }
4729 
4730   dbus_free_string_array (services);
4731 
4732   if (!check_send_exit_to_service (context, connection,
4733 				   EXISTENT_SERVICE_NAME, base_service))
4734     goto out;
4735 
4736   retval = TRUE;
4737 
4738  out:
4739   if (message)
4740     dbus_message_unref (message);
4741 
4742   if (base_service_message)
4743     dbus_message_unref (base_service_message);
4744 
4745   return retval;
4746 }
4747 
4748 typedef struct
4749 {
4750   Check2Func func;
4751   BusContext *context;
4752   DBusConnection *connection;
4753 } Check2Data;
4754 
4755 static dbus_bool_t
check_oom_check2_func(void * data)4756 check_oom_check2_func (void *data)
4757 {
4758   Check2Data *d = data;
4759 
4760   if (! (* d->func) (d->context, d->connection))
4761     return FALSE;
4762 
4763   if (!check_no_leftovers (d->context))
4764     {
4765       _dbus_warn ("Messages were left over, should be covered by test suite");
4766       return FALSE;
4767     }
4768 
4769   return TRUE;
4770 }
4771 
4772 static void
check2_try_iterations(BusContext * context,DBusConnection * connection,const char * description,Check2Func func)4773 check2_try_iterations (BusContext     *context,
4774                        DBusConnection *connection,
4775                        const char     *description,
4776                        Check2Func      func)
4777 {
4778   Check2Data d;
4779 
4780   d.func = func;
4781   d.context = context;
4782   d.connection = connection;
4783 
4784   if (!_dbus_test_oom_handling (description, check_oom_check2_func,
4785                                 &d))
4786     {
4787       _dbus_warn ("%s failed during oom", description);
4788       _dbus_assert_not_reached ("test failed");
4789     }
4790 }
4791 
4792 static dbus_bool_t
setenv_TEST_LAUNCH_HELPER_CONFIG(const DBusString * test_data_dir,const char * filename)4793 setenv_TEST_LAUNCH_HELPER_CONFIG(const DBusString *test_data_dir,
4794                                  const char       *filename)
4795 {
4796   DBusString full;
4797   DBusString file;
4798 
4799   if (!_dbus_string_init (&full))
4800     return FALSE;
4801 
4802   if (!_dbus_string_copy (test_data_dir, 0, &full, 0))
4803     {
4804       _dbus_string_free (&full);
4805       return FALSE;
4806     }
4807 
4808   _dbus_string_init_const (&file, filename);
4809 
4810   if (!_dbus_concat_dir_and_file (&full, &file))
4811     {
4812       _dbus_string_free (&full);
4813       return FALSE;
4814     }
4815 
4816   _dbus_verbose ("Setting TEST_LAUNCH_HELPER_CONFIG to '%s'\n",
4817                  _dbus_string_get_const_data (&full));
4818 
4819   dbus_setenv ("TEST_LAUNCH_HELPER_CONFIG", _dbus_string_get_const_data (&full));
4820 
4821   _dbus_string_free (&full);
4822 
4823   return TRUE;
4824 }
4825 
4826 static dbus_bool_t
bus_dispatch_test_conf(const DBusString * test_data_dir,const char * filename,dbus_bool_t use_launcher)4827 bus_dispatch_test_conf (const DBusString *test_data_dir,
4828 		        const char       *filename,
4829 		        dbus_bool_t       use_launcher)
4830 {
4831   BusContext *context;
4832   DBusConnection *foo;
4833   DBusConnection *bar;
4834   DBusConnection *baz;
4835   DBusError error;
4836 
4837   /* save the config name for the activation helper */
4838   if (!setenv_TEST_LAUNCH_HELPER_CONFIG (test_data_dir, filename))
4839     _dbus_assert_not_reached ("no memory setting TEST_LAUNCH_HELPER_CONFIG");
4840 
4841   dbus_error_init (&error);
4842 
4843   context = bus_context_new_test (test_data_dir, filename);
4844   if (context == NULL)
4845     return FALSE;
4846 
4847   foo = dbus_connection_open_private (TEST_DEBUG_PIPE, &error);
4848   if (foo == NULL)
4849     _dbus_assert_not_reached ("could not alloc connection");
4850 
4851   if (!bus_setup_debug_client (foo))
4852     _dbus_assert_not_reached ("could not set up connection");
4853 
4854   spin_connection_until_authenticated (context, foo);
4855 
4856   if (!check_hello_message (context, foo))
4857     _dbus_assert_not_reached ("hello message failed");
4858 
4859   if (!check_double_hello_message (context, foo))
4860     _dbus_assert_not_reached ("double hello message failed");
4861 
4862   if (!check_add_match (context, foo, ""))
4863     _dbus_assert_not_reached ("AddMatch message failed");
4864 
4865   bar = dbus_connection_open_private (TEST_DEBUG_PIPE, &error);
4866   if (bar == NULL)
4867     _dbus_assert_not_reached ("could not alloc connection");
4868 
4869   if (!bus_setup_debug_client (bar))
4870     _dbus_assert_not_reached ("could not set up connection");
4871 
4872   spin_connection_until_authenticated (context, bar);
4873 
4874   if (!check_hello_message (context, bar))
4875     _dbus_assert_not_reached ("hello message failed");
4876 
4877   if (!check_add_match (context, bar, ""))
4878     _dbus_assert_not_reached ("AddMatch message failed");
4879 
4880   baz = dbus_connection_open_private (TEST_DEBUG_PIPE, &error);
4881   if (baz == NULL)
4882     _dbus_assert_not_reached ("could not alloc connection");
4883 
4884   if (!bus_setup_debug_client (baz))
4885     _dbus_assert_not_reached ("could not set up connection");
4886 
4887   spin_connection_until_authenticated (context, baz);
4888 
4889   if (!check_hello_message (context, baz))
4890     _dbus_assert_not_reached ("hello message failed");
4891 
4892   if (!check_add_match (context, baz, ""))
4893     _dbus_assert_not_reached ("AddMatch message failed");
4894 
4895   if (!check_add_match (context, baz, "interface='com.example'"))
4896     _dbus_assert_not_reached ("AddMatch message failed");
4897 
4898 #ifdef DBUS_ENABLE_STATS
4899   if (!check_get_all_match_rules (context, baz))
4900     _dbus_assert_not_reached ("GetAllMatchRules message failed");
4901 #endif
4902 
4903   if (!check_get_connection_unix_user (context, baz))
4904     _dbus_assert_not_reached ("GetConnectionUnixUser message failed");
4905 
4906 #ifdef DBUS_WIN_FIXME
4907   _dbus_verbose("TODO: testing of GetConnectionUnixProcessID message skipped for now\n");
4908 #else
4909   if (!check_get_connection_unix_process_id (context, baz))
4910     _dbus_assert_not_reached ("GetConnectionUnixProcessID message failed");
4911 #endif
4912 
4913   if (!check_list_services (context, baz))
4914     _dbus_assert_not_reached ("ListActivatableNames message failed");
4915 
4916   if (!check_no_leftovers (context))
4917     {
4918       _dbus_warn ("Messages were left over after setting up initial connections");
4919       _dbus_assert_not_reached ("initial connection setup failed");
4920     }
4921 
4922   check1_try_iterations (context, "create_and_hello",
4923                          check_hello_connection);
4924 
4925   check2_try_iterations (context, foo, "nonexistent_service_no_auto_start",
4926                          check_nonexistent_service_no_auto_start);
4927 
4928   check2_try_iterations (context, foo, "segfault_service_no_auto_start",
4929                          check_segfault_service_no_auto_start);
4930 
4931   check2_try_iterations (context, foo, "existent_service_no_auto_start",
4932                          check_existent_service_no_auto_start);
4933 
4934   check2_try_iterations (context, foo, "nonexistent_service_auto_start",
4935                          check_nonexistent_service_auto_start);
4936 
4937   /* only do the segfault test if we are not using the launcher */
4938   check2_try_iterations (context, foo, "segfault_service_auto_start",
4939                          check_segfault_service_auto_start);
4940 
4941   /* only do the shell fail test if we are not using the launcher */
4942   check2_try_iterations (context, foo, "shell_fail_service_auto_start",
4943                          check_shell_fail_service_auto_start);
4944 
4945   /* specific to launcher */
4946   if (use_launcher)
4947     if (!check_launch_service_file_missing (context, foo))
4948       _dbus_assert_not_reached ("did not get service file not found error");
4949 
4950 #if 0
4951   /* Note: need to resolve some issues with the testing code in order to run
4952    * this in oom (handle that we sometimes don't get replies back from the bus
4953    * when oom happens, without blocking the test).
4954    */
4955   check2_try_iterations (context, foo, "existent_service_auto_auto_start",
4956                          check_existent_service_auto_start);
4957 #endif
4958 
4959   if (!check_existent_service_auto_start (context, foo))
4960     _dbus_assert_not_reached ("existent service auto start failed");
4961 
4962   if (!check_shell_service_success_auto_start (context, foo))
4963     _dbus_assert_not_reached ("shell success service auto start failed");
4964 
4965   _dbus_verbose ("Disconnecting foo, bar, and baz\n");
4966 
4967   kill_client_connection_unchecked (foo);
4968   kill_client_connection_unchecked (bar);
4969   kill_client_connection_unchecked (baz);
4970 
4971   bus_context_unref (context);
4972 
4973   return TRUE;
4974 }
4975 
4976 #ifndef DBUS_WIN
4977 static dbus_bool_t
bus_dispatch_test_conf_fail(const DBusString * test_data_dir,const char * filename)4978 bus_dispatch_test_conf_fail (const DBusString *test_data_dir,
4979 		             const char       *filename)
4980 {
4981   BusContext *context;
4982   DBusConnection *foo;
4983   DBusError error;
4984 
4985   /* save the config name for the activation helper */
4986   if (!setenv_TEST_LAUNCH_HELPER_CONFIG (test_data_dir, filename))
4987     _dbus_assert_not_reached ("no memory setting TEST_LAUNCH_HELPER_CONFIG");
4988 
4989   dbus_error_init (&error);
4990 
4991   context = bus_context_new_test (test_data_dir, filename);
4992   if (context == NULL)
4993     return FALSE;
4994 
4995   foo = dbus_connection_open_private (TEST_DEBUG_PIPE, &error);
4996   if (foo == NULL)
4997     _dbus_assert_not_reached ("could not alloc connection");
4998 
4999   if (!bus_setup_debug_client (foo))
5000     _dbus_assert_not_reached ("could not set up connection");
5001 
5002   spin_connection_until_authenticated (context, foo);
5003 
5004   if (!check_hello_message (context, foo))
5005     _dbus_assert_not_reached ("hello message failed");
5006 
5007   if (!check_double_hello_message (context, foo))
5008     _dbus_assert_not_reached ("double hello message failed");
5009 
5010   if (!check_add_match (context, foo, ""))
5011     _dbus_assert_not_reached ("AddMatch message failed");
5012 
5013   /* this only tests the activation.c user check */
5014   if (!check_launch_service_user_missing (context, foo))
5015     _dbus_assert_not_reached ("user missing did not trigger error");
5016 
5017   /* this only tests the desktop.c exec check */
5018   if (!check_launch_service_exec_missing (context, foo))
5019     _dbus_assert_not_reached ("exec missing did not trigger error");
5020 
5021   /* this only tests the desktop.c service check */
5022   if (!check_launch_service_service_missing (context, foo))
5023     _dbus_assert_not_reached ("service missing did not trigger error");
5024 
5025   _dbus_verbose ("Disconnecting foo\n");
5026 
5027   kill_client_connection_unchecked (foo);
5028 
5029   bus_context_unref (context);
5030 
5031   return TRUE;
5032 }
5033 #endif
5034 
5035 dbus_bool_t
bus_dispatch_test(const DBusString * test_data_dir)5036 bus_dispatch_test (const DBusString *test_data_dir)
5037 {
5038   /* run normal activation tests */
5039   _dbus_verbose ("Normal activation tests\n");
5040   if (!bus_dispatch_test_conf (test_data_dir,
5041   			       "valid-config-files/debug-allow-all.conf", FALSE))
5042     return FALSE;
5043 
5044 #ifndef DBUS_WIN
5045   /* run launch-helper activation tests */
5046   _dbus_verbose ("Launch helper activation tests\n");
5047   if (!bus_dispatch_test_conf (test_data_dir,
5048   			       "valid-config-files-system/debug-allow-all-pass.conf", TRUE))
5049     return FALSE;
5050 
5051   /* run select launch-helper activation tests on broken service files */
5052   if (!bus_dispatch_test_conf_fail (test_data_dir,
5053   			            "valid-config-files-system/debug-allow-all-fail.conf"))
5054     return FALSE;
5055 #endif
5056 
5057   return TRUE;
5058 }
5059 
5060 dbus_bool_t
bus_dispatch_sha1_test(const DBusString * test_data_dir)5061 bus_dispatch_sha1_test (const DBusString *test_data_dir)
5062 {
5063   BusContext *context;
5064   DBusConnection *foo;
5065   DBusError error;
5066 
5067   dbus_error_init (&error);
5068 
5069   /* Test SHA1 authentication */
5070   _dbus_verbose ("Testing SHA1 context\n");
5071 
5072   context = bus_context_new_test (test_data_dir,
5073                                   "valid-config-files/debug-allow-all-sha1.conf");
5074   if (context == NULL)
5075     return FALSE;
5076 
5077   foo = dbus_connection_open_private (TEST_DEBUG_PIPE, &error);
5078   if (foo == NULL)
5079     _dbus_assert_not_reached ("could not alloc connection");
5080 
5081   if (!bus_setup_debug_client (foo))
5082     _dbus_assert_not_reached ("could not set up connection");
5083 
5084   spin_connection_until_authenticated (context, foo);
5085 
5086   if (!check_hello_message (context, foo))
5087     _dbus_assert_not_reached ("hello message failed");
5088 
5089   if (!check_add_match (context, foo, ""))
5090     _dbus_assert_not_reached ("addmatch message failed");
5091 
5092   if (!check_no_leftovers (context))
5093     {
5094       _dbus_warn ("Messages were left over after setting up initial SHA-1 connection");
5095       _dbus_assert_not_reached ("initial connection setup failed");
5096     }
5097 
5098   check1_try_iterations (context, "create_and_hello_sha1",
5099                          check_hello_connection);
5100 
5101   kill_client_connection_unchecked (foo);
5102 
5103   bus_context_unref (context);
5104 
5105   return TRUE;
5106 }
5107 
5108 #ifdef HAVE_UNIX_FD_PASSING
5109 
5110 dbus_bool_t
bus_unix_fds_passing_test(const DBusString * test_data_dir)5111 bus_unix_fds_passing_test(const DBusString *test_data_dir)
5112 {
5113   BusContext *context;
5114   DBusConnection *foo, *bar;
5115   DBusError error;
5116   DBusMessage *m;
5117   DBusSocket one[2], two[2];
5118   int x, y, z;
5119   char r;
5120 
5121   dbus_error_init (&error);
5122 
5123   context = bus_context_new_test (test_data_dir, "valid-config-files/debug-allow-all.conf");
5124   if (context == NULL)
5125     _dbus_assert_not_reached ("could not alloc context");
5126 
5127   foo = dbus_connection_open_private (TEST_DEBUG_PIPE, &error);
5128   if (foo == NULL)
5129     _dbus_assert_not_reached ("could not alloc connection");
5130 
5131   if (!bus_setup_debug_client (foo))
5132     _dbus_assert_not_reached ("could not set up connection");
5133 
5134   spin_connection_until_authenticated (context, foo);
5135 
5136   if (!check_hello_message (context, foo))
5137     _dbus_assert_not_reached ("hello message failed");
5138 
5139   if (!check_add_match (context, foo, ""))
5140     _dbus_assert_not_reached ("AddMatch message failed");
5141 
5142   bar = dbus_connection_open_private (TEST_DEBUG_PIPE, &error);
5143   if (bar == NULL)
5144     _dbus_assert_not_reached ("could not alloc connection");
5145 
5146   if (!bus_setup_debug_client (bar))
5147     _dbus_assert_not_reached ("could not set up connection");
5148 
5149   spin_connection_until_authenticated (context, bar);
5150 
5151   if (!check_hello_message (context, bar))
5152     _dbus_assert_not_reached ("hello message failed");
5153 
5154   if (!check_add_match (context, bar, ""))
5155     _dbus_assert_not_reached ("AddMatch message failed");
5156 
5157   if (!(m = dbus_message_new_signal("/", "a.b.c", "d")))
5158     _dbus_assert_not_reached ("could not alloc message");
5159 
5160   if (!(_dbus_socketpair (one, one+1, TRUE, &error)))
5161     _dbus_assert_not_reached("Failed to allocate pipe #1");
5162 
5163   if (!(_dbus_socketpair (two, two+1, TRUE, &error)))
5164     _dbus_assert_not_reached("Failed to allocate pipe #2");
5165 
5166   if (!dbus_message_append_args(m,
5167                                 DBUS_TYPE_UNIX_FD, one,
5168                                 DBUS_TYPE_UNIX_FD, two,
5169                                 DBUS_TYPE_UNIX_FD, two,
5170                                 DBUS_TYPE_INVALID))
5171     _dbus_assert_not_reached("Failed to attach fds.");
5172 
5173   if (!_dbus_close_socket (one[0], &error))
5174     _dbus_assert_not_reached("Failed to close pipe #1 ");
5175   if (!_dbus_close_socket (two[0], &error))
5176     _dbus_assert_not_reached("Failed to close pipe #2 ");
5177 
5178   if (!(dbus_connection_can_send_type(foo, DBUS_TYPE_UNIX_FD)))
5179     _dbus_assert_not_reached("Connection cannot do fd passing");
5180 
5181   if (!(dbus_connection_can_send_type(bar, DBUS_TYPE_UNIX_FD)))
5182     _dbus_assert_not_reached("Connection cannot do fd passing");
5183 
5184   if (!dbus_connection_send (foo, m, NULL))
5185     _dbus_assert_not_reached("Failed to send fds");
5186 
5187   dbus_message_unref(m);
5188 
5189   bus_test_run_clients_loop (SEND_PENDING (foo));
5190 
5191   bus_test_run_everything (context);
5192 
5193   block_connection_until_message_from_bus (context, foo, "unix fd reception on foo");
5194 
5195   if (!(m = pop_message_waiting_for_memory (foo)))
5196     _dbus_assert_not_reached("Failed to receive msg");
5197 
5198   if (!dbus_message_is_signal(m, "a.b.c", "d"))
5199     _dbus_assert_not_reached("bogus message received");
5200 
5201   dbus_message_unref(m);
5202 
5203   block_connection_until_message_from_bus (context, bar, "unix fd reception on bar");
5204 
5205   if (!(m = pop_message_waiting_for_memory (bar)))
5206     _dbus_assert_not_reached("Failed to receive msg");
5207 
5208   if (!dbus_message_is_signal(m, "a.b.c", "d"))
5209     _dbus_assert_not_reached("bogus message received");
5210 
5211   if (!dbus_message_get_args(m,
5212                              &error,
5213                              DBUS_TYPE_UNIX_FD, &x,
5214                              DBUS_TYPE_UNIX_FD, &y,
5215                              DBUS_TYPE_UNIX_FD, &z,
5216                              DBUS_TYPE_INVALID))
5217     _dbus_assert_not_reached("Failed to parse fds.");
5218 
5219   dbus_message_unref(m);
5220 
5221   if (write(x, "X", 1) != 1)
5222     _dbus_assert_not_reached("Failed to write to pipe #1");
5223   if (write(y, "Y", 1) != 1)
5224     _dbus_assert_not_reached("Failed to write to pipe #2");
5225   if (write(z, "Z", 1) != 1)
5226     _dbus_assert_not_reached("Failed to write to pipe #2/2nd fd");
5227 
5228   if (!_dbus_close(x, &error))
5229     _dbus_assert_not_reached("Failed to close pipe #1/other side ");
5230   if (!_dbus_close(y, &error))
5231     _dbus_assert_not_reached("Failed to close pipe #2/other side ");
5232   if (!_dbus_close(z, &error))
5233     _dbus_assert_not_reached("Failed to close pipe #2/other size 2nd fd ");
5234 
5235   if (read(one[1].fd, &r, 1) != 1 || r != 'X')
5236     _dbus_assert_not_reached("Failed to read value from pipe.");
5237   if (read(two[1].fd, &r, 1) != 1 || r != 'Y')
5238     _dbus_assert_not_reached("Failed to read value from pipe.");
5239   if (read(two[1].fd, &r, 1) != 1 || r != 'Z')
5240     _dbus_assert_not_reached("Failed to read value from pipe.");
5241 
5242   if (!_dbus_close_socket (one[1], &error))
5243     _dbus_assert_not_reached("Failed to close pipe #1 ");
5244   if (!_dbus_close_socket (two[1], &error))
5245     _dbus_assert_not_reached("Failed to close pipe #2 ");
5246 
5247   _dbus_verbose ("Disconnecting foo\n");
5248   kill_client_connection_unchecked (foo);
5249 
5250   _dbus_verbose ("Disconnecting bar\n");
5251   kill_client_connection_unchecked (bar);
5252 
5253   bus_context_unref (context);
5254 
5255   return TRUE;
5256 }
5257 #endif
5258 
5259 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */
5260