Add uid, pid, and command to security logs
[platform/upstream/dbus.git] / bus / connection.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* connection.c  Client connections
3  *
4  * Copyright (C) 2003  Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 2.1
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23 #include "connection.h"
24 #include "dispatch.h"
25 #include "policy.h"
26 #include "services.h"
27 #include "utils.h"
28 #include "signals.h"
29 #include "expirelist.h"
30 #include "selinux.h"
31 #include <dbus/dbus-list.h>
32 #include <dbus/dbus-hash.h>
33 #include <dbus/dbus-timeout.h>
34
35 /* Trim executed commands to this length; we want to keep logs readable */
36 #define MAX_LOG_COMMAND_LEN 50
37
38 static void bus_connection_remove_transactions (DBusConnection *connection);
39
40 typedef struct
41 {
42   BusExpireItem expire_item;
43
44   DBusConnection *will_get_reply;
45   DBusConnection *will_send_reply;
46
47   dbus_uint32_t reply_serial;
48   
49 } BusPendingReply;
50
51 struct BusConnections
52 {
53   int refcount;
54   DBusList *completed;  /**< List of all completed connections */
55   int n_completed;      /**< Length of completed list */
56   DBusList *incomplete; /**< List of all not-yet-active connections */
57   int n_incomplete;     /**< Length of incomplete list */
58   BusContext *context;
59   DBusHashTable *completed_by_user; /**< Number of completed connections for each UID */
60   DBusTimeout *expire_timeout; /**< Timeout for expiring incomplete connections. */
61   int stamp;                   /**< Incrementing number */
62   BusExpireList *pending_replies; /**< List of pending replies */
63 };
64
65 static dbus_int32_t connection_data_slot = -1;
66
67 typedef struct
68 {
69   BusConnections *connections;
70   DBusList *link_in_connection_list;
71   DBusConnection *connection;
72   DBusList *services_owned;
73   int n_services_owned;
74   DBusList *match_rules;
75   int n_match_rules;
76   char *name;
77   DBusList *transaction_messages; /**< Stuff we need to send as part of a transaction */
78   DBusMessage *oom_message;
79   DBusPreallocatedSend *oom_preallocated;
80   BusClientPolicy *policy;
81
82   char *cached_loginfo_string;
83   BusSELinuxID *selinux_id;
84
85   long connection_tv_sec;  /**< Time when we connected (seconds component) */
86   long connection_tv_usec; /**< Time when we connected (microsec component) */
87   int stamp;               /**< connections->stamp last time we were traversed */
88 } BusConnectionData;
89
90 static dbus_bool_t bus_pending_reply_expired (BusExpireList *list,
91                                               DBusList      *link,
92                                               void          *data);
93
94 static void bus_connection_drop_pending_replies (BusConnections  *connections,
95                                                  DBusConnection  *connection);
96
97 static dbus_bool_t expire_incomplete_timeout (void *data);
98
99 #define BUS_CONNECTION_DATA(connection) (dbus_connection_get_data ((connection), connection_data_slot))
100
101 static DBusLoop*
102 connection_get_loop (DBusConnection *connection)
103 {
104   BusConnectionData *d;
105
106   d = BUS_CONNECTION_DATA (connection);
107
108   return bus_context_get_loop (d->connections->context);
109 }
110
111
112 static int
113 get_connections_for_uid (BusConnections *connections,
114                          dbus_uid_t      uid)
115 {
116   void *val;
117   int current_count;
118
119   /* val is NULL is 0 when it isn't in the hash yet */
120   
121   val = _dbus_hash_table_lookup_ulong (connections->completed_by_user,
122                                        uid);
123
124   current_count = _DBUS_POINTER_TO_INT (val);
125
126   return current_count;
127 }
128
129 static dbus_bool_t
130 adjust_connections_for_uid (BusConnections *connections,
131                             dbus_uid_t      uid,
132                             int             adjustment)
133 {
134   int current_count;
135
136   current_count = get_connections_for_uid (connections, uid);
137
138   _dbus_verbose ("Adjusting connection count for UID " DBUS_UID_FORMAT
139                  ": was %d adjustment %d making %d\n",
140                  uid, current_count, adjustment, current_count + adjustment);
141   
142   _dbus_assert (current_count >= 0);
143   
144   current_count += adjustment;
145
146   _dbus_assert (current_count >= 0);
147
148   if (current_count == 0)
149     {
150       _dbus_hash_table_remove_ulong (connections->completed_by_user, uid);
151       return TRUE;
152     }
153   else
154     {
155       dbus_bool_t retval;
156       
157       retval = _dbus_hash_table_insert_ulong (connections->completed_by_user,
158                                               uid, _DBUS_INT_TO_POINTER (current_count));
159
160       /* only positive adjustment can fail as otherwise
161        * a hash entry should already exist
162        */
163       _dbus_assert (adjustment > 0 ||
164                     (adjustment <= 0 && retval));
165
166       return retval;
167     }
168 }
169
170 void
171 bus_connection_disconnected (DBusConnection *connection)
172 {
173   BusConnectionData *d;
174   BusService *service;
175   BusMatchmaker *matchmaker;
176   
177   d = BUS_CONNECTION_DATA (connection);
178   _dbus_assert (d != NULL);
179
180   _dbus_verbose ("%s disconnected, dropping all service ownership and releasing\n",
181                  d->name ? d->name : "(inactive)");
182
183   /* Delete our match rules */
184   if (d->n_match_rules > 0)
185     {
186       matchmaker = bus_context_get_matchmaker (d->connections->context);
187       bus_matchmaker_disconnected (matchmaker, connection);
188     }
189   
190   /* Drop any service ownership. Unfortunately, this requires
191    * memory allocation and there doesn't seem to be a good way to
192    * handle it other than sleeping; we can't "fail" the operation of
193    * disconnecting a client, and preallocating a broadcast "service is
194    * now gone" message for every client-service pair seems kind of
195    * involved.
196    */
197   while ((service = _dbus_list_get_last (&d->services_owned)))
198     {
199       BusTransaction *transaction;
200       DBusError error;
201
202     retry:
203       
204       dbus_error_init (&error);
205         
206       while ((transaction = bus_transaction_new (d->connections->context)) == NULL)
207         _dbus_wait_for_memory ();
208         
209       if (!bus_service_remove_owner (service, connection,
210                                      transaction, &error))
211         {
212           _DBUS_ASSERT_ERROR_IS_SET (&error);
213           
214           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
215             {
216               dbus_error_free (&error);
217               bus_transaction_cancel_and_free (transaction);
218               _dbus_wait_for_memory ();
219               goto retry;
220             }
221           else
222             {
223               _dbus_verbose ("Failed to remove service owner: %s %s\n",
224                              error.name, error.message);
225               _dbus_assert_not_reached ("Removing service owner failed for non-memory-related reason");
226             }
227         }
228         
229       bus_transaction_execute_and_free (transaction);
230     }
231
232   bus_dispatch_remove_connection (connection);
233   
234   /* no more watching */
235   if (!dbus_connection_set_watch_functions (connection,
236                                             NULL, NULL, NULL,
237                                             connection,
238                                             NULL))
239     _dbus_assert_not_reached ("setting watch functions to NULL failed");
240
241   if (!dbus_connection_set_timeout_functions (connection,
242                                               NULL, NULL, NULL,
243                                               connection,
244                                               NULL))
245     _dbus_assert_not_reached ("setting timeout functions to NULL failed");
246   
247   dbus_connection_set_unix_user_function (connection,
248                                           NULL, NULL, NULL);
249   dbus_connection_set_windows_user_function (connection,
250                                              NULL, NULL, NULL);
251   
252   dbus_connection_set_dispatch_status_function (connection,
253                                                 NULL, NULL, NULL);
254   
255   bus_connection_remove_transactions (connection);
256
257   if (d->link_in_connection_list != NULL)
258     {
259       if (d->name != NULL)
260         {
261           unsigned long uid;
262           
263           _dbus_list_remove_link (&d->connections->completed, d->link_in_connection_list);
264           d->link_in_connection_list = NULL;
265           d->connections->n_completed -= 1;
266
267           if (dbus_connection_get_unix_user (connection, &uid))
268             {
269               if (!adjust_connections_for_uid (d->connections,
270                                                uid, -1))
271                 _dbus_assert_not_reached ("adjusting downward should never fail");
272             }
273         }
274       else
275         {
276           _dbus_list_remove_link (&d->connections->incomplete, d->link_in_connection_list);
277           d->link_in_connection_list = NULL;
278           d->connections->n_incomplete -= 1;
279         }
280       
281       _dbus_assert (d->connections->n_incomplete >= 0);
282       _dbus_assert (d->connections->n_completed >= 0);
283     }
284
285   bus_connection_drop_pending_replies (d->connections, connection);
286   
287   /* frees "d" as side effect */
288   dbus_connection_set_data (connection,
289                             connection_data_slot,
290                             NULL, NULL);
291   
292   dbus_connection_unref (connection);
293 }
294
295 static dbus_bool_t
296 connection_watch_callback (DBusWatch     *watch,
297                            unsigned int   condition,
298                            void          *data)
299 {
300  /* FIXME this can be done in dbus-mainloop.c
301   * if the code in activation.c for the babysitter
302   * watch handler is fixed.
303   */
304   
305 #if 0
306   _dbus_verbose ("Calling handle_watch\n");
307 #endif
308   return dbus_watch_handle (watch, condition);
309 }
310
311 static dbus_bool_t
312 add_connection_watch (DBusWatch      *watch,
313                       void           *data)
314 {
315   DBusConnection *connection = data;
316
317   return _dbus_loop_add_watch (connection_get_loop (connection),
318                                watch, connection_watch_callback, connection,
319                                NULL);
320 }
321
322 static void
323 remove_connection_watch (DBusWatch      *watch,
324                          void           *data)
325 {
326   DBusConnection *connection = data;
327   
328   _dbus_loop_remove_watch (connection_get_loop (connection),
329                            watch, connection_watch_callback, connection);
330 }
331
332 static void
333 connection_timeout_callback (DBusTimeout   *timeout,
334                              void          *data)
335 {
336   /* DBusConnection *connection = data; */
337
338   /* can return FALSE on OOM but we just let it fire again later */
339   dbus_timeout_handle (timeout);
340 }
341
342 static dbus_bool_t
343 add_connection_timeout (DBusTimeout    *timeout,
344                         void           *data)
345 {
346   DBusConnection *connection = data;
347   
348   return _dbus_loop_add_timeout (connection_get_loop (connection),
349                                  timeout, connection_timeout_callback, connection, NULL);
350 }
351
352 static void
353 remove_connection_timeout (DBusTimeout    *timeout,
354                            void           *data)
355 {
356   DBusConnection *connection = data;
357   
358   _dbus_loop_remove_timeout (connection_get_loop (connection),
359                              timeout, connection_timeout_callback, connection);
360 }
361
362 static void
363 dispatch_status_function (DBusConnection    *connection,
364                           DBusDispatchStatus new_status,
365                           void              *data)
366 {
367   DBusLoop *loop = data;
368   
369   if (new_status != DBUS_DISPATCH_COMPLETE)
370     {
371       while (!_dbus_loop_queue_dispatch (loop, connection))
372         _dbus_wait_for_memory ();
373     }
374 }
375
376 static dbus_bool_t
377 allow_unix_user_function (DBusConnection *connection,
378                           unsigned long   uid,
379                           void           *data)
380 {
381   BusConnectionData *d;
382     
383   d = BUS_CONNECTION_DATA (connection);
384
385   _dbus_assert (d != NULL);
386   
387   return bus_context_allow_unix_user (d->connections->context, uid);
388 }
389
390 static void
391 free_connection_data (void *data)
392 {
393   BusConnectionData *d = data;
394
395   /* services_owned should be NULL since we should be disconnected */
396   _dbus_assert (d->services_owned == NULL);
397   _dbus_assert (d->n_services_owned == 0);
398   /* similarly */
399   _dbus_assert (d->transaction_messages == NULL);
400
401   if (d->oom_preallocated)
402     dbus_connection_free_preallocated_send (d->connection, d->oom_preallocated);
403
404   if (d->oom_message)
405     dbus_message_unref (d->oom_message);
406
407   if (d->policy)
408     bus_client_policy_unref (d->policy);
409
410   if (d->selinux_id)
411     bus_selinux_id_unref (d->selinux_id);
412   
413   dbus_free (d->cached_loginfo_string);
414   
415   dbus_free (d->name);
416   
417   dbus_free (d);
418 }
419
420 static void
421 call_timeout_callback (DBusTimeout   *timeout,
422                        void          *data)
423 {
424   /* can return FALSE on OOM but we just let it fire again later */
425   dbus_timeout_handle (timeout);
426 }
427
428 BusConnections*
429 bus_connections_new (BusContext *context)
430 {
431   BusConnections *connections;
432
433   if (!dbus_connection_allocate_data_slot (&connection_data_slot))
434     goto failed_0;
435
436   connections = dbus_new0 (BusConnections, 1);
437   if (connections == NULL)
438     goto failed_1;
439
440   connections->completed_by_user = _dbus_hash_table_new (DBUS_HASH_ULONG,
441                                                          NULL, NULL);
442   if (connections->completed_by_user == NULL)
443     goto failed_2;
444
445   connections->expire_timeout = _dbus_timeout_new (100, /* irrelevant */
446                                                    expire_incomplete_timeout,
447                                                    connections, NULL);
448   if (connections->expire_timeout == NULL)
449     goto failed_3;
450
451   _dbus_timeout_set_enabled (connections->expire_timeout, FALSE);
452
453   connections->pending_replies = bus_expire_list_new (bus_context_get_loop (context),
454                                                       bus_context_get_reply_timeout (context),
455                                                       bus_pending_reply_expired,
456                                                       connections);
457   if (connections->pending_replies == NULL)
458     goto failed_4;
459   
460   if (!_dbus_loop_add_timeout (bus_context_get_loop (context),
461                                connections->expire_timeout,
462                                call_timeout_callback, NULL, NULL))
463     goto failed_5;
464   
465   connections->refcount = 1;
466   connections->context = context;
467   
468   return connections;
469
470  failed_5:
471   bus_expire_list_free (connections->pending_replies);
472  failed_4:
473   _dbus_timeout_unref (connections->expire_timeout);
474  failed_3:
475   _dbus_hash_table_unref (connections->completed_by_user);
476  failed_2:
477   dbus_free (connections);
478  failed_1:
479   dbus_connection_free_data_slot (&connection_data_slot);
480  failed_0:
481   return NULL;
482 }
483
484 BusConnections *
485 bus_connections_ref (BusConnections *connections)
486 {
487   _dbus_assert (connections->refcount > 0);
488   connections->refcount += 1;
489
490   return connections;
491 }
492
493 void
494 bus_connections_unref (BusConnections *connections)
495 {
496   _dbus_assert (connections->refcount > 0);
497   connections->refcount -= 1;
498   if (connections->refcount == 0)
499     {
500       /* drop all incomplete */
501       while (connections->incomplete != NULL)
502         {
503           DBusConnection *connection;
504
505           connection = connections->incomplete->data;
506
507           dbus_connection_ref (connection);
508           dbus_connection_close (connection);
509           bus_connection_disconnected (connection);
510           dbus_connection_unref (connection);
511         }
512
513       _dbus_assert (connections->n_incomplete == 0);
514       
515       /* drop all real connections */
516       while (connections->completed != NULL)
517         {
518           DBusConnection *connection;
519
520           connection = connections->completed->data;
521
522           dbus_connection_ref (connection);
523           dbus_connection_close (connection);
524           bus_connection_disconnected (connection);
525           dbus_connection_unref (connection);
526         }
527
528       _dbus_assert (connections->n_completed == 0);
529
530       bus_expire_list_free (connections->pending_replies);
531       
532       _dbus_loop_remove_timeout (bus_context_get_loop (connections->context),
533                                  connections->expire_timeout,
534                                  call_timeout_callback, NULL);
535       
536       _dbus_timeout_unref (connections->expire_timeout);
537       
538       _dbus_hash_table_unref (connections->completed_by_user);
539       
540       dbus_free (connections);
541
542       dbus_connection_free_data_slot (&connection_data_slot);
543     }
544 }
545
546 /* Used for logging */
547 static dbus_bool_t
548 cache_peer_loginfo_string (BusConnectionData *d, 
549                            DBusConnection    *connection)
550 {
551   DBusString loginfo_buf;
552   unsigned long uid;
553   unsigned long pid;
554   char *windows_sid;
555   dbus_bool_t prev_added;
556
557   if (!_dbus_string_init (&loginfo_buf))
558     return FALSE;
559   
560   prev_added = FALSE;
561   if (dbus_connection_get_unix_user (connection, &uid))
562     {
563       if (!_dbus_string_append_printf (&loginfo_buf, "uid=%ld", uid))
564         goto oom;
565       else
566         prev_added = TRUE;
567     }
568
569   if (dbus_connection_get_unix_process_id (connection, &pid))
570     {
571       if (prev_added)
572         {
573           if (!_dbus_string_append_byte (&loginfo_buf, ' '))
574             goto oom;
575         }
576       if (!_dbus_string_append_printf (&loginfo_buf, "pid=%ld comm=\"", pid))
577         goto oom;
578       /* Ignore errors here */
579       if (_dbus_command_for_pid (pid, &loginfo_buf, MAX_LOG_COMMAND_LEN, NULL))
580         {
581           if (!_dbus_string_append_byte (&loginfo_buf, '"'))
582             goto oom;
583         }
584     }
585
586   if (dbus_connection_get_windows_user (connection, &windows_sid))
587     {
588       if (!_dbus_string_append_printf (&loginfo_buf, "sid=\"%s\" ", windows_sid))
589         goto oom;
590       dbus_free (windows_sid);
591     }
592
593   if (!_dbus_string_steal_data (&loginfo_buf, &(d->cached_loginfo_string)))
594     goto oom;
595
596   _dbus_string_free (&loginfo_buf); 
597
598   return TRUE;
599 oom:
600    _dbus_string_free (&loginfo_buf);
601    return FALSE;
602 }
603
604 dbus_bool_t
605 bus_connections_setup_connection (BusConnections *connections,
606                                   DBusConnection *connection)
607 {
608
609   BusConnectionData *d;
610   dbus_bool_t retval;
611   DBusError error;
612
613   
614   d = dbus_new0 (BusConnectionData, 1);
615   
616   if (d == NULL)
617     return FALSE;
618
619   d->connections = connections;
620   d->connection = connection;
621   
622   _dbus_get_current_time (&d->connection_tv_sec,
623                           &d->connection_tv_usec);
624   
625   _dbus_assert (connection_data_slot >= 0);
626   
627   if (!dbus_connection_set_data (connection,
628                                  connection_data_slot,
629                                  d, free_connection_data))
630     {
631       dbus_free (d);
632       return FALSE;
633     }
634
635   dbus_connection_set_route_peer_messages (connection, TRUE);
636   
637   retval = FALSE;
638
639   dbus_error_init (&error);
640   d->selinux_id = bus_selinux_init_connection_id (connection,
641                                                   &error);
642   if (dbus_error_is_set (&error))
643     {
644       /* This is a bit bogus because we pretend all errors
645        * are OOM; this is done because we know that in bus.c
646        * an OOM error disconnects the connection, which is
647        * the same thing we want on any other error.
648        */
649       dbus_error_free (&error);
650       goto out;
651     }
652
653   if (!dbus_connection_set_watch_functions (connection,
654                                             add_connection_watch,
655                                             remove_connection_watch,
656                                             NULL,
657                                             connection,
658                                             NULL))
659     goto out;
660   
661   if (!dbus_connection_set_timeout_functions (connection,
662                                               add_connection_timeout,
663                                               remove_connection_timeout,
664                                               NULL,
665                                               connection, NULL))
666     goto out;
667
668   /* For now we don't need to set a Windows user function because
669    * there are no policies in the config file controlling what
670    * Windows users can connect. The default 'same user that owns the
671    * bus can connect' behavior of DBusConnection is fine on Windows.
672    */
673   dbus_connection_set_unix_user_function (connection,
674                                           allow_unix_user_function,
675                                           NULL, NULL);
676
677   dbus_connection_set_dispatch_status_function (connection,
678                                                 dispatch_status_function,
679                                                 bus_context_get_loop (connections->context),
680                                                 NULL);
681
682   d->link_in_connection_list = _dbus_list_alloc_link (connection);
683   if (d->link_in_connection_list == NULL)
684     goto out;
685   
686   /* Setup the connection with the dispatcher */
687   if (!bus_dispatch_add_connection (connection))
688     goto out;
689
690   if (dbus_connection_get_dispatch_status (connection) != DBUS_DISPATCH_COMPLETE)
691     {
692       if (!_dbus_loop_queue_dispatch (bus_context_get_loop (connections->context), connection))
693         {
694           bus_dispatch_remove_connection (connection);
695           goto out;
696         }
697     }
698
699   _dbus_list_append_link (&connections->incomplete, d->link_in_connection_list);
700   connections->n_incomplete += 1;
701   
702   dbus_connection_ref (connection);
703
704   /* Note that we might disconnect ourselves here, but it only takes
705    * effect on return to the main loop. We call this to free up
706    * expired connections if possible, and to queue the timeout for our
707    * own expiration.
708    */
709   bus_connections_expire_incomplete (connections);
710   
711   /* And we might also disconnect ourselves here, but again it
712    * only takes effect on return to main loop.
713    */
714   if (connections->n_incomplete >
715       bus_context_get_max_incomplete_connections (connections->context))
716     {
717       _dbus_verbose ("Number of incomplete connections exceeds max, dropping oldest one\n");
718       
719       _dbus_assert (connections->incomplete != NULL);
720       /* Disconnect the oldest unauthenticated connection.  FIXME
721        * would it be more secure to drop a *random* connection?  This
722        * algorithm seems to mean that if someone can create new
723        * connections quickly enough, they can keep anyone else from
724        * completing authentication. But random may or may not really
725        * help with that, a more elaborate solution might be required.
726        */
727       dbus_connection_close (connections->incomplete->data);
728     }
729   
730   retval = TRUE;
731
732  out:
733   if (!retval)
734     {
735       if (d->selinux_id)
736         bus_selinux_id_unref (d->selinux_id);
737       d->selinux_id = NULL;
738       
739       if (!dbus_connection_set_watch_functions (connection,
740                                                 NULL, NULL, NULL,
741                                                 connection,
742                                                 NULL))
743         _dbus_assert_not_reached ("setting watch functions to NULL failed");
744       
745       if (!dbus_connection_set_timeout_functions (connection,
746                                                   NULL, NULL, NULL,
747                                                   connection,
748                                                   NULL))
749         _dbus_assert_not_reached ("setting timeout functions to NULL failed");
750
751       dbus_connection_set_unix_user_function (connection,
752                                               NULL, NULL, NULL);
753
754       dbus_connection_set_windows_user_function (connection,
755                                                  NULL, NULL, NULL);
756       
757       dbus_connection_set_dispatch_status_function (connection,
758                                                     NULL, NULL, NULL);
759
760       if (d->link_in_connection_list != NULL)
761         {
762           _dbus_assert (d->link_in_connection_list->next == NULL);
763           _dbus_assert (d->link_in_connection_list->prev == NULL);
764           _dbus_list_free_link (d->link_in_connection_list);
765           d->link_in_connection_list = NULL;
766         }
767       
768       if (!dbus_connection_set_data (connection,
769                                      connection_data_slot,
770                                      NULL, NULL))
771         _dbus_assert_not_reached ("failed to set connection data to null");
772
773       /* "d" has now been freed */
774     }
775   
776   return retval;
777 }
778
779 void
780 bus_connections_expire_incomplete (BusConnections *connections)
781 {    
782   int next_interval;
783
784   next_interval = -1;
785   
786   if (connections->incomplete != NULL)
787     {
788       long tv_sec, tv_usec;
789       DBusList *link;
790       int auth_timeout;
791       
792       _dbus_get_current_time (&tv_sec, &tv_usec);
793       auth_timeout = bus_context_get_auth_timeout (connections->context);
794   
795       link = _dbus_list_get_first_link (&connections->incomplete);
796       while (link != NULL)
797         {
798           DBusList *next = _dbus_list_get_next_link (&connections->incomplete, link);
799           DBusConnection *connection;
800           BusConnectionData *d;
801           double elapsed;
802       
803           connection = link->data;
804       
805           d = BUS_CONNECTION_DATA (connection);
806       
807           _dbus_assert (d != NULL);
808       
809           elapsed = ELAPSED_MILLISECONDS_SINCE (d->connection_tv_sec,
810                                                 d->connection_tv_usec,
811                                                 tv_sec, tv_usec);
812
813           if (elapsed >= (double) auth_timeout)
814             {
815               _dbus_verbose ("Timing out authentication for connection %p\n", connection);
816               dbus_connection_close (connection);
817             }
818           else
819             {
820               /* We can end the loop, since the connections are in oldest-first order */
821               next_interval = ((double)auth_timeout) - elapsed;
822               _dbus_verbose ("Connection %p authentication expires in %d milliseconds\n",
823                              connection, next_interval);
824           
825               break;
826             }
827       
828           link = next;
829         }
830     }
831
832   bus_expire_timeout_set_interval (connections->expire_timeout,
833                                    next_interval);
834 }
835
836 static dbus_bool_t
837 expire_incomplete_timeout (void *data)
838 {
839   BusConnections *connections = data;
840
841   _dbus_verbose ("Running %s\n", _DBUS_FUNCTION_NAME);
842   
843   /* note that this may remove the timeout */
844   bus_connections_expire_incomplete (connections);
845
846   return TRUE;
847 }
848
849 dbus_bool_t
850 bus_connection_get_unix_groups  (DBusConnection   *connection,
851                                  unsigned long   **groups,
852                                  int              *n_groups,
853                                  DBusError        *error)
854 {
855   BusConnectionData *d;
856   unsigned long uid;
857   
858   d = BUS_CONNECTION_DATA (connection);
859
860   _dbus_assert (d != NULL);
861
862   *groups = NULL;
863   *n_groups = 0;
864
865   if (dbus_connection_get_unix_user (connection, &uid))
866     {
867       if (!_dbus_unix_groups_from_uid (uid, groups, n_groups))
868         {
869           _dbus_verbose ("Did not get any groups for UID %lu\n",
870                          uid);
871           return FALSE;
872         }
873       else
874         {
875           _dbus_verbose ("Got %d groups for UID %lu\n",
876                          *n_groups, uid);
877           return TRUE;
878         }
879     }
880   else
881     return TRUE; /* successfully got 0 groups */
882 }
883
884 dbus_bool_t
885 bus_connection_is_in_unix_group (DBusConnection *connection,
886                                  unsigned long   gid)
887 {
888   int i;
889   unsigned long *group_ids;
890   int n_group_ids;
891
892   if (!bus_connection_get_unix_groups (connection, &group_ids, &n_group_ids,
893                                        NULL))
894     return FALSE;
895
896   i = 0;
897   while (i < n_group_ids)
898     {
899       if (group_ids[i] == gid)
900         {
901           dbus_free (group_ids);
902           return TRUE;
903         }
904       ++i;
905     }
906
907   dbus_free (group_ids);
908   return FALSE;
909 }
910
911 const char *
912 bus_connection_get_loginfo (DBusConnection        *connection)
913 {
914   BusConnectionData *d;
915     
916   d = BUS_CONNECTION_DATA (connection);
917
918   if (!bus_connection_is_active (connection))
919     return "inactive";
920   return d->cached_loginfo_string;  
921 }
922
923 BusClientPolicy*
924 bus_connection_get_policy (DBusConnection *connection)
925 {
926   BusConnectionData *d;
927     
928   d = BUS_CONNECTION_DATA (connection);
929
930   _dbus_assert (d != NULL);
931   _dbus_assert (d->policy != NULL);
932   
933   return d->policy;
934 }
935
936 static dbus_bool_t
937 foreach_active (BusConnections               *connections,
938                 BusConnectionForeachFunction  function,
939                 void                         *data)
940 {
941   DBusList *link;
942   
943   link = _dbus_list_get_first_link (&connections->completed);
944   while (link != NULL)
945     {
946       DBusConnection *connection = link->data;
947       DBusList *next = _dbus_list_get_next_link (&connections->completed, link);
948
949       if (!(* function) (connection, data))
950         return FALSE;
951       
952       link = next;
953     }
954
955   return TRUE;
956 }
957
958 static dbus_bool_t
959 foreach_inactive (BusConnections               *connections,
960                   BusConnectionForeachFunction  function,
961                   void                         *data)
962 {
963   DBusList *link;
964   
965   link = _dbus_list_get_first_link (&connections->incomplete);
966   while (link != NULL)
967     {
968       DBusConnection *connection = link->data;
969       DBusList *next = _dbus_list_get_next_link (&connections->incomplete, link);
970
971       if (!(* function) (connection, data))
972         return FALSE;
973       
974       link = next;
975     }
976
977   return TRUE;
978 }
979
980 /**
981  * Calls function on each active connection; if the function returns
982  * #FALSE, stops iterating. Active connections are authenticated
983  * and have sent a Hello message.
984  *
985  * @param connections the connections object
986  * @param function the function
987  * @param data data to pass to it as a second arg
988  */
989 void
990 bus_connections_foreach_active (BusConnections               *connections,
991                                 BusConnectionForeachFunction  function,
992                                 void                         *data)
993 {
994   foreach_active (connections, function, data);
995 }
996
997 /**
998  * Calls function on each connection; if the function returns
999  * #FALSE, stops iterating.
1000  *
1001  * @param connections the connections object
1002  * @param function the function
1003  * @param data data to pass to it as a second arg
1004  */
1005 void
1006 bus_connections_foreach (BusConnections               *connections,
1007                          BusConnectionForeachFunction  function,
1008                          void                         *data)
1009 {
1010   if (!foreach_active (connections, function, data))
1011     return;
1012
1013   foreach_inactive (connections, function, data);
1014 }
1015
1016 BusContext*
1017 bus_connections_get_context (BusConnections *connections)
1018 {
1019   return connections->context;
1020 }
1021
1022 /*
1023  * This is used to avoid covering the same connection twice when
1024  * traversing connections. Note that it assumes we will
1025  * bus_connection_mark_stamp() each connection at least once per
1026  * INT_MAX increments of the global stamp, or wraparound would break
1027  * things.
1028  */
1029 void
1030 bus_connections_increment_stamp (BusConnections *connections)
1031 {
1032   connections->stamp += 1;
1033 }
1034
1035 /* Mark connection with current stamp, return TRUE if it
1036  * didn't already have that stamp
1037  */
1038 dbus_bool_t
1039 bus_connection_mark_stamp (DBusConnection *connection)
1040 {
1041   BusConnectionData *d;
1042   
1043   d = BUS_CONNECTION_DATA (connection);
1044   
1045   _dbus_assert (d != NULL);
1046
1047   if (d->stamp == d->connections->stamp)
1048     return FALSE;
1049   else
1050     {
1051       d->stamp = d->connections->stamp;
1052       return TRUE;
1053     }
1054 }
1055
1056 BusContext*
1057 bus_connection_get_context (DBusConnection *connection)
1058 {
1059   BusConnectionData *d;
1060
1061   d = BUS_CONNECTION_DATA (connection);
1062
1063   _dbus_assert (d != NULL);
1064
1065   return d->connections->context;
1066 }
1067
1068 BusConnections*
1069 bus_connection_get_connections (DBusConnection *connection)
1070 {
1071   BusConnectionData *d;
1072     
1073   d = BUS_CONNECTION_DATA (connection);
1074
1075   _dbus_assert (d != NULL);
1076
1077   return d->connections;
1078 }
1079
1080 BusRegistry*
1081 bus_connection_get_registry (DBusConnection *connection)
1082 {
1083   BusConnectionData *d;
1084
1085   d = BUS_CONNECTION_DATA (connection);
1086
1087   _dbus_assert (d != NULL);
1088
1089   return bus_context_get_registry (d->connections->context);
1090 }
1091
1092 BusActivation*
1093 bus_connection_get_activation (DBusConnection *connection)
1094 {
1095   BusConnectionData *d;
1096
1097   d = BUS_CONNECTION_DATA (connection);
1098
1099   _dbus_assert (d != NULL);
1100
1101   return bus_context_get_activation (d->connections->context);
1102 }
1103
1104 BusMatchmaker*
1105 bus_connection_get_matchmaker (DBusConnection *connection)
1106 {
1107   BusConnectionData *d;
1108
1109   d = BUS_CONNECTION_DATA (connection);
1110
1111   _dbus_assert (d != NULL);
1112
1113   return bus_context_get_matchmaker (d->connections->context);
1114 }
1115
1116 BusSELinuxID*
1117 bus_connection_get_selinux_id (DBusConnection *connection)
1118 {
1119   BusConnectionData *d;
1120
1121   d = BUS_CONNECTION_DATA (connection);
1122
1123   _dbus_assert (d != NULL);
1124
1125   return d->selinux_id;
1126 }
1127
1128 /**
1129  * Checks whether the connection is registered with the message bus.
1130  *
1131  * @param connection the connection
1132  * @returns #TRUE if we're an active message bus participant
1133  */
1134 dbus_bool_t
1135 bus_connection_is_active (DBusConnection *connection)
1136 {
1137   BusConnectionData *d;
1138
1139   d = BUS_CONNECTION_DATA (connection);
1140   
1141   return d != NULL && d->name != NULL;
1142 }
1143
1144 dbus_bool_t
1145 bus_connection_preallocate_oom_error (DBusConnection *connection)
1146 {
1147   DBusMessage *message;
1148   DBusPreallocatedSend *preallocated;
1149   BusConnectionData *d;
1150
1151   d = BUS_CONNECTION_DATA (connection);  
1152
1153   _dbus_assert (d != NULL);
1154
1155   if (d->oom_preallocated != NULL)
1156     return TRUE;
1157   
1158   preallocated = dbus_connection_preallocate_send (connection);
1159   if (preallocated == NULL)
1160     return FALSE;
1161
1162   message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
1163
1164   if (message == NULL)
1165     {
1166       dbus_connection_free_preallocated_send (connection, preallocated);
1167       return FALSE;
1168     }
1169
1170   /* d->name may be NULL, but that is OK */
1171   if (!dbus_message_set_error_name (message, DBUS_ERROR_NO_MEMORY) ||
1172       !dbus_message_set_destination (message, d->name) ||
1173       !dbus_message_set_sender (message,
1174                                 DBUS_SERVICE_DBUS))
1175     {
1176       dbus_connection_free_preallocated_send (connection, preallocated);
1177       dbus_message_unref (message);
1178       return FALSE;
1179     }
1180   
1181   /* set reply serial to placeholder value just so space is already allocated
1182    * for it.
1183    */
1184   if (!dbus_message_set_reply_serial (message, 14))
1185     {
1186       dbus_connection_free_preallocated_send (connection, preallocated);
1187       dbus_message_unref (message);
1188       return FALSE;
1189     }
1190
1191   d->oom_message = message;
1192   d->oom_preallocated = preallocated;
1193   
1194   return TRUE;
1195 }
1196
1197 void
1198 bus_connection_send_oom_error (DBusConnection *connection,
1199                                DBusMessage    *in_reply_to)
1200 {
1201   BusConnectionData *d;
1202
1203   d = BUS_CONNECTION_DATA (connection);  
1204
1205   _dbus_assert (d != NULL);  
1206   _dbus_assert (d->oom_message != NULL);
1207
1208   /* should always succeed since we set it to a placeholder earlier */
1209   if (!dbus_message_set_reply_serial (d->oom_message,
1210                                       dbus_message_get_serial (in_reply_to)))
1211     _dbus_assert_not_reached ("Failed to set reply serial for preallocated oom message");
1212
1213   _dbus_assert (dbus_message_get_sender (d->oom_message) != NULL);
1214   
1215   dbus_connection_send_preallocated (connection, d->oom_preallocated,
1216                                      d->oom_message, NULL);
1217
1218   dbus_message_unref (d->oom_message);
1219   d->oom_message = NULL;
1220   d->oom_preallocated = NULL;
1221 }
1222
1223 void
1224 bus_connection_add_match_rule_link (DBusConnection *connection,
1225                                     DBusList       *link)
1226 {
1227   BusConnectionData *d;
1228
1229   d = BUS_CONNECTION_DATA (connection);
1230   _dbus_assert (d != NULL);
1231
1232   _dbus_list_append_link (&d->match_rules, link);
1233
1234   d->n_match_rules += 1;
1235 }
1236
1237 dbus_bool_t
1238 bus_connection_add_match_rule (DBusConnection *connection,
1239                                BusMatchRule   *rule)
1240 {
1241     DBusList *link;
1242
1243   link = _dbus_list_alloc_link (rule);
1244
1245   if (link == NULL)
1246     return FALSE;
1247
1248   bus_connection_add_match_rule_link (connection, link);
1249
1250   return TRUE;
1251 }
1252
1253 void
1254 bus_connection_remove_match_rule (DBusConnection *connection,
1255                                   BusMatchRule   *rule)
1256 {
1257   BusConnectionData *d;
1258
1259   d = BUS_CONNECTION_DATA (connection);
1260   _dbus_assert (d != NULL);
1261
1262   _dbus_list_remove_last (&d->match_rules, rule);
1263
1264   d->n_match_rules -= 1;
1265   _dbus_assert (d->n_match_rules >= 0);
1266 }
1267
1268 int
1269 bus_connection_get_n_match_rules (DBusConnection *connection)
1270 {
1271   BusConnectionData *d;
1272
1273   d = BUS_CONNECTION_DATA (connection);
1274   _dbus_assert (d != NULL);
1275   
1276   return d->n_match_rules;
1277 }
1278
1279 void
1280 bus_connection_add_owned_service_link (DBusConnection *connection,
1281                                        DBusList       *link)
1282 {
1283   BusConnectionData *d;
1284
1285   d = BUS_CONNECTION_DATA (connection);
1286   _dbus_assert (d != NULL);
1287
1288   _dbus_list_append_link (&d->services_owned, link);
1289
1290   d->n_services_owned += 1;
1291 }
1292
1293 dbus_bool_t
1294 bus_connection_add_owned_service (DBusConnection *connection,
1295                                   BusService     *service)
1296 {
1297   DBusList *link;
1298
1299   link = _dbus_list_alloc_link (service);
1300
1301   if (link == NULL)
1302     return FALSE;
1303
1304   bus_connection_add_owned_service_link (connection, link);
1305
1306   return TRUE;
1307 }
1308
1309 void
1310 bus_connection_remove_owned_service (DBusConnection *connection,
1311                                      BusService     *service)
1312 {
1313   BusConnectionData *d;
1314
1315   d = BUS_CONNECTION_DATA (connection);
1316   _dbus_assert (d != NULL);
1317
1318   _dbus_list_remove_last (&d->services_owned, service);
1319
1320   d->n_services_owned -= 1;
1321   _dbus_assert (d->n_services_owned >= 0);
1322 }
1323
1324 int
1325 bus_connection_get_n_services_owned (DBusConnection *connection)
1326 {
1327   BusConnectionData *d;
1328
1329   d = BUS_CONNECTION_DATA (connection);
1330   _dbus_assert (d != NULL);
1331   
1332   return d->n_services_owned;
1333 }
1334
1335 dbus_bool_t
1336 bus_connection_complete (DBusConnection   *connection,
1337                          const DBusString *name,
1338                          DBusError        *error)
1339 {
1340   BusConnectionData *d;
1341   unsigned long uid;
1342   
1343   d = BUS_CONNECTION_DATA (connection);
1344   _dbus_assert (d != NULL);
1345   _dbus_assert (d->name == NULL);
1346   _dbus_assert (d->policy == NULL);
1347
1348   _dbus_assert (!bus_connection_is_active (connection));
1349   
1350   if (!_dbus_string_copy_data (name, &d->name))
1351     {
1352       BUS_SET_OOM (error);
1353       return FALSE;
1354     }
1355
1356   _dbus_assert (d->name != NULL);
1357   
1358   _dbus_verbose ("Name %s assigned to %p\n", d->name, connection);
1359
1360   d->policy = bus_context_create_client_policy (d->connections->context,
1361                                                 connection,
1362                                                 error);
1363
1364   /* we may have a NULL policy on OOM or error getting list of
1365    * groups for a user. In the latter case we don't handle it so
1366    * well currently, as it will just keep failing over and over.
1367    */
1368
1369   if (d->policy == NULL)
1370     {
1371       _dbus_verbose ("Failed to create security policy for connection %p\n",
1372                      connection);
1373       _DBUS_ASSERT_ERROR_IS_SET (error);
1374       dbus_free (d->name);
1375       d->name = NULL;
1376       return FALSE;
1377     }
1378   
1379   if (dbus_connection_get_unix_user (connection, &uid))
1380     {
1381       if (!adjust_connections_for_uid (d->connections,
1382                                        uid, 1))
1383         goto fail;
1384     }
1385
1386   /* Create and cache a string which holds information about the 
1387    * peer process; used for logging purposes.
1388    */
1389   if (!cache_peer_loginfo_string (d, connection))
1390     goto fail;
1391
1392   /* Now the connection is active, move it between lists */
1393   _dbus_list_unlink (&d->connections->incomplete,
1394                      d->link_in_connection_list);
1395   d->connections->n_incomplete -= 1;
1396   _dbus_list_append_link (&d->connections->completed,
1397                           d->link_in_connection_list);
1398   d->connections->n_completed += 1;
1399
1400   _dbus_assert (d->connections->n_incomplete >= 0);
1401   _dbus_assert (d->connections->n_completed > 0);
1402
1403   /* See if we can remove the timeout */
1404   bus_connections_expire_incomplete (d->connections);
1405
1406   _dbus_assert (bus_connection_is_active (connection));
1407   
1408   return TRUE;
1409 fail:
1410   BUS_SET_OOM (error);
1411   dbus_free (d->name);
1412   d->name = NULL;
1413   if (d->policy)
1414     bus_client_policy_unref (d->policy);
1415   d->policy = NULL;
1416   return FALSE;
1417 }
1418
1419 const char *
1420 bus_connection_get_name (DBusConnection *connection)
1421 {
1422   BusConnectionData *d;
1423   
1424   d = BUS_CONNECTION_DATA (connection);
1425   _dbus_assert (d != NULL);
1426   
1427   return d->name;
1428 }
1429
1430 /**
1431  * Check whether completing the passed-in connection would
1432  * exceed limits, and if so set error and return #FALSE
1433  */
1434 dbus_bool_t
1435 bus_connections_check_limits (BusConnections  *connections,
1436                               DBusConnection  *requesting_completion,
1437                               DBusError       *error)
1438 {
1439   BusConnectionData *d;
1440   unsigned long uid;
1441   
1442   d = BUS_CONNECTION_DATA (requesting_completion);
1443   _dbus_assert (d != NULL);
1444
1445   _dbus_assert (d->name == NULL);
1446
1447   if (connections->n_completed >=
1448       bus_context_get_max_completed_connections (connections->context))
1449     {
1450       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
1451                       "The maximum number of active connections has been reached");
1452       return FALSE;
1453     }
1454   
1455   if (dbus_connection_get_unix_user (requesting_completion, &uid))
1456     {
1457       if (get_connections_for_uid (connections, uid) >=
1458           bus_context_get_max_connections_per_user (connections->context))
1459         {
1460           dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
1461                           "The maximum number of active connections for UID %lu has been reached",
1462                           uid);
1463           return FALSE;
1464         }
1465     }
1466   
1467   return TRUE;
1468 }
1469
1470 static void
1471 bus_pending_reply_free (BusPendingReply *pending)
1472 {
1473   _dbus_verbose ("Freeing pending reply %p, replier %p receiver %p serial %u\n",
1474                  pending,
1475                  pending->will_send_reply,
1476                  pending->will_get_reply,
1477                  pending->reply_serial);
1478
1479   dbus_free (pending);
1480 }
1481
1482 static dbus_bool_t
1483 bus_pending_reply_send_no_reply (BusConnections  *connections,
1484                                  BusTransaction  *transaction,
1485                                  BusPendingReply *pending)
1486 {
1487   DBusMessage *message;
1488   DBusMessageIter iter;
1489   dbus_bool_t retval;
1490   const char *errmsg;
1491
1492   retval = FALSE;
1493   
1494   message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
1495   if (message == NULL)
1496     return FALSE;
1497   
1498   dbus_message_set_no_reply (message, TRUE);
1499   
1500   if (!dbus_message_set_reply_serial (message,
1501                                       pending->reply_serial))
1502     goto out;
1503
1504   if (!dbus_message_set_error_name (message,
1505                                     DBUS_ERROR_NO_REPLY))
1506     goto out;
1507
1508   errmsg = "Message did not receive a reply (timeout by message bus)";
1509   dbus_message_iter_init_append (message, &iter);
1510   if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &errmsg))
1511     goto out;
1512     
1513   if (!bus_transaction_send_from_driver (transaction, pending->will_get_reply,
1514                                          message))
1515     goto out;
1516
1517   retval = TRUE;
1518
1519  out:
1520   dbus_message_unref (message);
1521   return retval;
1522 }
1523
1524 static dbus_bool_t
1525 bus_pending_reply_expired (BusExpireList *list,
1526                            DBusList      *link,
1527                            void          *data)
1528 {
1529   BusPendingReply *pending = link->data;
1530   BusConnections *connections = data;
1531   BusTransaction *transaction;
1532   
1533   /* No reply is forthcoming. So nuke it if we can. If not,
1534    * leave it in the list to try expiring again later when we
1535    * get more memory.
1536    */
1537
1538   _dbus_verbose ("Expiring pending reply %p, replier %p receiver %p serial %u\n",
1539                  pending,
1540                  pending->will_send_reply,
1541                  pending->will_get_reply,
1542                  pending->reply_serial);
1543   
1544   transaction = bus_transaction_new (connections->context);
1545   if (transaction == NULL)
1546     return FALSE;
1547   
1548   if (!bus_pending_reply_send_no_reply (connections,
1549                                         transaction,
1550                                         pending))
1551     {
1552       bus_transaction_cancel_and_free (transaction);
1553       return FALSE;
1554     }
1555
1556   bus_expire_list_remove_link (connections->pending_replies, link);
1557
1558   bus_pending_reply_free (pending);
1559   bus_transaction_execute_and_free (transaction);
1560
1561   return TRUE;
1562 }
1563
1564 static void
1565 bus_connection_drop_pending_replies (BusConnections  *connections,
1566                                      DBusConnection  *connection)
1567 {
1568   /* The DBusConnection is almost 100% finalized here, so you can't
1569    * do anything with it except check for pointer equality
1570    */
1571   DBusList *link;
1572
1573   _dbus_verbose ("Dropping pending replies that involve connection %p\n",
1574                  connection);
1575   
1576   link = bus_expire_list_get_first_link (connections->pending_replies);
1577   while (link != NULL)
1578     {
1579       DBusList *next;
1580       BusPendingReply *pending;
1581
1582       next = bus_expire_list_get_next_link (connections->pending_replies,
1583                                             link);
1584       pending = link->data;
1585
1586       if (pending->will_get_reply == connection)
1587         {
1588           /* We don't need to track this pending reply anymore */
1589
1590           _dbus_verbose ("Dropping pending reply %p, replier %p receiver %p serial %u\n",
1591                          pending,
1592                          pending->will_send_reply,
1593                          pending->will_get_reply,
1594                          pending->reply_serial);
1595           
1596           bus_expire_list_remove_link (connections->pending_replies,
1597                                        link);
1598           bus_pending_reply_free (pending);
1599         }
1600       else if (pending->will_send_reply == connection)
1601         {
1602           /* The reply isn't going to be sent, so set things
1603            * up so it will be expired right away
1604            */
1605           _dbus_verbose ("Will expire pending reply %p, replier %p receiver %p serial %u\n",
1606                          pending,
1607                          pending->will_send_reply,
1608                          pending->will_get_reply,
1609                          pending->reply_serial);
1610           
1611           pending->will_send_reply = NULL;
1612           pending->expire_item.added_tv_sec = 0;
1613           pending->expire_item.added_tv_usec = 0;
1614
1615           bus_expire_list_recheck_immediately (connections->pending_replies);
1616         }
1617       
1618       link = next;
1619     }
1620 }
1621
1622
1623 typedef struct
1624 {
1625   BusPendingReply *pending;
1626   BusConnections  *connections;
1627 } CancelPendingReplyData;
1628
1629 static void
1630 cancel_pending_reply (void *data)
1631 {
1632   CancelPendingReplyData *d = data;
1633
1634   _dbus_verbose ("%s: d = %p\n", _DBUS_FUNCTION_NAME, d);
1635   
1636   if (!bus_expire_list_remove (d->connections->pending_replies,
1637                                &d->pending->expire_item))
1638     _dbus_assert_not_reached ("pending reply did not exist to be cancelled");
1639
1640   bus_pending_reply_free (d->pending); /* since it's been cancelled */
1641 }
1642
1643 static void
1644 cancel_pending_reply_data_free (void *data)
1645 {
1646   CancelPendingReplyData *d = data;
1647
1648   _dbus_verbose ("%s: d = %p\n", _DBUS_FUNCTION_NAME, d);
1649   
1650   /* d->pending should be either freed or still
1651    * in the list of pending replies (owned by someone
1652    * else)
1653    */
1654   
1655   dbus_free (d);
1656 }
1657
1658 /*
1659  * Record that a reply is allowed; return TRUE on success.
1660  */
1661 dbus_bool_t
1662 bus_connections_expect_reply (BusConnections  *connections,
1663                               BusTransaction  *transaction,
1664                               DBusConnection  *will_get_reply,
1665                               DBusConnection  *will_send_reply,
1666                               DBusMessage     *reply_to_this,
1667                               DBusError       *error)
1668 {
1669   BusPendingReply *pending;
1670   dbus_uint32_t reply_serial;
1671   DBusList *link;
1672   CancelPendingReplyData *cprd;
1673   int count;
1674
1675   _dbus_assert (will_get_reply != NULL);
1676   _dbus_assert (will_send_reply != NULL);
1677   _dbus_assert (reply_to_this != NULL);
1678   
1679   if (dbus_message_get_no_reply (reply_to_this))
1680     return TRUE; /* we won't allow a reply, since client doesn't care for one. */
1681   
1682   reply_serial = dbus_message_get_serial (reply_to_this);
1683
1684   link = bus_expire_list_get_first_link (connections->pending_replies);
1685   count = 0;
1686   while (link != NULL)
1687     {
1688       pending = link->data;
1689
1690       if (pending->reply_serial == reply_serial &&
1691           pending->will_get_reply == will_get_reply &&
1692           pending->will_send_reply == will_send_reply)
1693         {
1694           dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
1695                           "Message has the same reply serial as a currently-outstanding existing method call");
1696           return FALSE;
1697         }
1698       
1699       link = bus_expire_list_get_next_link (connections->pending_replies,
1700                                             link);
1701       if (pending->will_get_reply == will_get_reply)
1702         ++count;
1703     }
1704   
1705   if (count >=
1706       bus_context_get_max_replies_per_connection (connections->context))
1707     {
1708       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
1709                       "The maximum number of pending replies per connection has been reached");
1710       return FALSE;
1711     }
1712
1713   pending = dbus_new0 (BusPendingReply, 1);
1714   if (pending == NULL)
1715     {
1716       BUS_SET_OOM (error);
1717       return FALSE;
1718     }
1719
1720 #ifdef DBUS_ENABLE_VERBOSE_MODE
1721   /* so we can see a not-yet-added pending reply */
1722   pending->expire_item.added_tv_sec = 1;
1723   pending->expire_item.added_tv_usec = 1;
1724 #endif
1725
1726   pending->will_get_reply = will_get_reply;
1727   pending->will_send_reply = will_send_reply;
1728   pending->reply_serial = reply_serial;
1729   
1730   cprd = dbus_new0 (CancelPendingReplyData, 1);
1731   if (cprd == NULL)
1732     {
1733       BUS_SET_OOM (error);
1734       bus_pending_reply_free (pending);
1735       return FALSE;
1736     }
1737   
1738   if (!bus_expire_list_add (connections->pending_replies,
1739                             &pending->expire_item))
1740     {
1741       BUS_SET_OOM (error);
1742       dbus_free (cprd);
1743       bus_pending_reply_free (pending);
1744       return FALSE;
1745     }
1746
1747   if (!bus_transaction_add_cancel_hook (transaction,
1748                                         cancel_pending_reply,
1749                                         cprd,
1750                                         cancel_pending_reply_data_free))
1751     {
1752       BUS_SET_OOM (error);
1753       bus_expire_list_remove (connections->pending_replies, &pending->expire_item);
1754       dbus_free (cprd);
1755       bus_pending_reply_free (pending);
1756       return FALSE;
1757     }
1758                                         
1759   cprd->pending = pending;
1760   cprd->connections = connections;
1761   
1762   _dbus_get_current_time (&pending->expire_item.added_tv_sec,
1763                           &pending->expire_item.added_tv_usec);
1764
1765   _dbus_verbose ("Added pending reply %p, replier %p receiver %p serial %u\n",
1766                  pending,
1767                  pending->will_send_reply,
1768                  pending->will_get_reply,
1769                  pending->reply_serial);
1770   
1771   return TRUE;
1772 }
1773
1774 typedef struct
1775 {
1776   DBusList        *link;
1777   BusConnections  *connections;
1778 } CheckPendingReplyData;
1779
1780 static void
1781 cancel_check_pending_reply (void *data)
1782 {
1783   CheckPendingReplyData *d = data;
1784
1785   _dbus_verbose ("%s: d = %p\n", _DBUS_FUNCTION_NAME, d);
1786
1787   bus_expire_list_add_link (d->connections->pending_replies,
1788                             d->link);
1789   d->link = NULL;
1790 }
1791
1792 static void
1793 check_pending_reply_data_free (void *data)
1794 {
1795   CheckPendingReplyData *d = data;
1796
1797   _dbus_verbose ("%s: d = %p\n", _DBUS_FUNCTION_NAME, d);
1798   
1799   if (d->link != NULL)
1800     {
1801       BusPendingReply *pending = d->link->data;
1802       
1803       _dbus_assert (!bus_expire_list_contains_item (d->connections->pending_replies,
1804                                                     &pending->expire_item));
1805       
1806       bus_pending_reply_free (pending);
1807       _dbus_list_free_link (d->link);
1808     }
1809   
1810   dbus_free (d);
1811 }
1812
1813 /*
1814  * Check whether a reply is allowed, remove BusPendingReply
1815  * if so, return TRUE if so.
1816  */
1817 dbus_bool_t
1818 bus_connections_check_reply (BusConnections *connections,
1819                              BusTransaction *transaction,
1820                              DBusConnection *sending_reply,
1821                              DBusConnection *receiving_reply,
1822                              DBusMessage    *reply,
1823                              DBusError      *error)
1824 {
1825   CheckPendingReplyData *cprd;
1826   DBusList *link;
1827   dbus_uint32_t reply_serial;
1828   
1829   _dbus_assert (sending_reply != NULL);
1830   _dbus_assert (receiving_reply != NULL);
1831
1832   reply_serial = dbus_message_get_reply_serial (reply);
1833
1834   link = bus_expire_list_get_first_link (connections->pending_replies);
1835   while (link != NULL)
1836     {
1837       BusPendingReply *pending = link->data;
1838
1839       if (pending->reply_serial == reply_serial &&
1840           pending->will_get_reply == receiving_reply &&
1841           pending->will_send_reply == sending_reply)
1842         {
1843           _dbus_verbose ("Found pending reply with serial %u\n", reply_serial);
1844           break;
1845         }
1846       
1847       link = bus_expire_list_get_next_link (connections->pending_replies,
1848                                             link);
1849     }
1850
1851   if (link == NULL)
1852     {
1853       _dbus_verbose ("No pending reply expected\n");
1854
1855       return FALSE;
1856     }
1857
1858   cprd = dbus_new0 (CheckPendingReplyData, 1);
1859   if (cprd == NULL)
1860     {
1861       BUS_SET_OOM (error);
1862       return FALSE;
1863     }
1864   
1865   if (!bus_transaction_add_cancel_hook (transaction,
1866                                         cancel_check_pending_reply,
1867                                         cprd,
1868                                         check_pending_reply_data_free))
1869     {
1870       BUS_SET_OOM (error);
1871       dbus_free (cprd);
1872       return FALSE;
1873     }
1874
1875   cprd->link = link;
1876   cprd->connections = connections;
1877   
1878   bus_expire_list_unlink (connections->pending_replies,
1879                           link);
1880   
1881   _dbus_assert (!bus_expire_list_contains_item (connections->pending_replies, link->data));
1882
1883   return TRUE;
1884 }
1885
1886 /*
1887  * Transactions
1888  *
1889  * Note that this is fairly fragile; in particular, don't try to use
1890  * one transaction across any main loop iterations.
1891  */
1892
1893 typedef struct
1894 {
1895   BusTransaction *transaction;
1896   DBusMessage    *message;
1897   DBusPreallocatedSend *preallocated;
1898 } MessageToSend;
1899
1900 typedef struct
1901 {
1902   BusTransactionCancelFunction cancel_function;
1903   DBusFreeFunction free_data_function;
1904   void *data;
1905 } CancelHook;
1906
1907 struct BusTransaction
1908 {
1909   DBusList *connections;
1910   BusContext *context;
1911   DBusList *cancel_hooks;
1912 };
1913
1914 static void
1915 message_to_send_free (DBusConnection *connection,
1916                       MessageToSend  *to_send)
1917 {
1918   if (to_send->message)
1919     dbus_message_unref (to_send->message);
1920
1921   if (to_send->preallocated)
1922     dbus_connection_free_preallocated_send (connection, to_send->preallocated);
1923
1924   dbus_free (to_send);
1925 }
1926
1927 static void
1928 cancel_hook_cancel (void *element,
1929                     void *data)
1930 {
1931   CancelHook *ch = element;
1932
1933   _dbus_verbose ("Running transaction cancel hook\n");
1934   
1935   if (ch->cancel_function)
1936     (* ch->cancel_function) (ch->data);  
1937 }
1938
1939 static void
1940 cancel_hook_free (void *element,
1941                   void *data)
1942 {
1943   CancelHook *ch = element;
1944
1945   if (ch->free_data_function)
1946     (* ch->free_data_function) (ch->data);
1947
1948   dbus_free (ch);
1949 }
1950
1951 static void
1952 free_cancel_hooks (BusTransaction *transaction)
1953 {
1954   _dbus_list_foreach (&transaction->cancel_hooks,
1955                       cancel_hook_free, NULL);
1956   
1957   _dbus_list_clear (&transaction->cancel_hooks);
1958 }
1959
1960 BusTransaction*
1961 bus_transaction_new (BusContext *context)
1962 {
1963   BusTransaction *transaction;
1964
1965   transaction = dbus_new0 (BusTransaction, 1);
1966   if (transaction == NULL)
1967     return NULL;
1968
1969   transaction->context = context;
1970   
1971   return transaction;
1972 }
1973
1974 BusContext*
1975 bus_transaction_get_context (BusTransaction  *transaction)
1976 {
1977   return transaction->context;
1978 }
1979
1980 BusConnections*
1981 bus_transaction_get_connections (BusTransaction  *transaction)
1982 {
1983   return bus_context_get_connections (transaction->context);
1984 }
1985
1986 dbus_bool_t
1987 bus_transaction_send_from_driver (BusTransaction *transaction,
1988                                   DBusConnection *connection,
1989                                   DBusMessage    *message)
1990 {
1991   /* We have to set the sender to the driver, and have
1992    * to check security policy since it was not done in
1993    * dispatch.c
1994    */
1995   _dbus_verbose ("Sending %s %s %s from driver\n",
1996                  dbus_message_get_interface (message) ?
1997                  dbus_message_get_interface (message) : "(no interface)",
1998                  dbus_message_get_member (message) ?
1999                  dbus_message_get_member (message) : "(no member)",
2000                  dbus_message_get_error_name (message) ?
2001                  dbus_message_get_error_name (message) : "(no error name)");
2002                  
2003   if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
2004     return FALSE;
2005
2006   if (bus_connection_is_active (connection))
2007     {
2008       if (!dbus_message_set_destination (message,
2009                                          bus_connection_get_name (connection)))
2010         return FALSE;
2011     }
2012   
2013   /* bus driver never wants a reply */
2014   dbus_message_set_no_reply (message, TRUE);
2015   
2016   /* If security policy doesn't allow the message, we silently
2017    * eat it; the driver doesn't care about getting a reply.
2018    */
2019   if (!bus_context_check_security_policy (bus_transaction_get_context (transaction),
2020                                           transaction,
2021                                           NULL, connection, connection, message, NULL))
2022     return TRUE;
2023
2024   return bus_transaction_send (transaction, connection, message);
2025 }
2026
2027 dbus_bool_t
2028 bus_transaction_send (BusTransaction *transaction,
2029                       DBusConnection *connection,
2030                       DBusMessage    *message)
2031 {
2032   MessageToSend *to_send;
2033   BusConnectionData *d;
2034   DBusList *link;
2035
2036   _dbus_verbose ("  trying to add %s interface=%s member=%s error=%s to transaction%s\n",
2037                  dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ? "error" :
2038                  dbus_message_get_reply_serial (message) != 0 ? "reply" :
2039                  "message",
2040                  dbus_message_get_interface (message) ?
2041                  dbus_message_get_interface (message) : "(unset)",
2042                  dbus_message_get_member (message) ?
2043                  dbus_message_get_member (message) : "(unset)",
2044                  dbus_message_get_error_name (message) ?
2045                  dbus_message_get_error_name (message) : "(unset)",
2046                  dbus_connection_get_is_connected (connection) ?
2047                  "" : " (disconnected)");
2048
2049   _dbus_assert (dbus_message_get_sender (message) != NULL);
2050   
2051   if (!dbus_connection_get_is_connected (connection))
2052     return TRUE; /* silently ignore disconnected connections */
2053   
2054   d = BUS_CONNECTION_DATA (connection);
2055   _dbus_assert (d != NULL);
2056   
2057   to_send = dbus_new (MessageToSend, 1);
2058   if (to_send == NULL)
2059     {
2060       return FALSE;
2061     }
2062
2063   to_send->preallocated = dbus_connection_preallocate_send (connection);
2064   if (to_send->preallocated == NULL)
2065     {
2066       dbus_free (to_send);
2067       return FALSE;
2068     }  
2069   
2070   dbus_message_ref (message);
2071   to_send->message = message;
2072   to_send->transaction = transaction;
2073
2074   _dbus_verbose ("about to prepend message\n");
2075   
2076   if (!_dbus_list_prepend (&d->transaction_messages, to_send))
2077     {
2078       message_to_send_free (connection, to_send);
2079       return FALSE;
2080     }
2081
2082   _dbus_verbose ("prepended message\n");
2083   
2084   /* See if we already had this connection in the list
2085    * for this transaction. If we have a pending message,
2086    * then we should already be in transaction->connections
2087    */
2088   link = _dbus_list_get_first_link (&d->transaction_messages);
2089   _dbus_assert (link->data == to_send);
2090   link = _dbus_list_get_next_link (&d->transaction_messages, link);
2091   while (link != NULL)
2092     {
2093       MessageToSend *m = link->data;
2094       DBusList *next = _dbus_list_get_next_link (&d->transaction_messages, link);
2095       
2096       if (m->transaction == transaction)
2097         break;
2098         
2099       link = next;
2100     }
2101
2102   if (link == NULL)
2103     {
2104       if (!_dbus_list_prepend (&transaction->connections, connection))
2105         {
2106           _dbus_list_remove (&d->transaction_messages, to_send);
2107           message_to_send_free (connection, to_send);
2108           return FALSE;
2109         }
2110     }
2111
2112   return TRUE;
2113 }
2114
2115 static void
2116 connection_cancel_transaction (DBusConnection *connection,
2117                                BusTransaction *transaction)
2118 {
2119   DBusList *link;
2120   BusConnectionData *d;
2121   
2122   d = BUS_CONNECTION_DATA (connection);
2123   _dbus_assert (d != NULL);
2124   
2125   link = _dbus_list_get_first_link (&d->transaction_messages);
2126   while (link != NULL)
2127     {
2128       MessageToSend *m = link->data;
2129       DBusList *next = _dbus_list_get_next_link (&d->transaction_messages, link);
2130       
2131       if (m->transaction == transaction)
2132         {
2133           _dbus_list_remove_link (&d->transaction_messages,
2134                                   link);
2135           
2136           message_to_send_free (connection, m);
2137         }
2138         
2139       link = next;
2140     }
2141 }
2142
2143 void
2144 bus_transaction_cancel_and_free (BusTransaction *transaction)
2145 {
2146   DBusConnection *connection;
2147
2148   _dbus_verbose ("TRANSACTION: cancelled\n");
2149   
2150   while ((connection = _dbus_list_pop_first (&transaction->connections)))
2151     connection_cancel_transaction (connection, transaction);
2152
2153   _dbus_assert (transaction->connections == NULL);
2154
2155   _dbus_list_foreach (&transaction->cancel_hooks,
2156                       cancel_hook_cancel, NULL);
2157
2158   free_cancel_hooks (transaction);
2159   
2160   dbus_free (transaction);
2161 }
2162
2163 static void
2164 connection_execute_transaction (DBusConnection *connection,
2165                                 BusTransaction *transaction)
2166 {
2167   DBusList *link;
2168   BusConnectionData *d;
2169   
2170   d = BUS_CONNECTION_DATA (connection);
2171   _dbus_assert (d != NULL);
2172
2173   /* Send the queue in order (FIFO) */
2174   link = _dbus_list_get_last_link (&d->transaction_messages);
2175   while (link != NULL)
2176     {
2177       MessageToSend *m = link->data;
2178       DBusList *prev = _dbus_list_get_prev_link (&d->transaction_messages, link);
2179       
2180       if (m->transaction == transaction)
2181         {
2182           _dbus_list_remove_link (&d->transaction_messages,
2183                                   link);
2184
2185           _dbus_assert (dbus_message_get_sender (m->message) != NULL);
2186           
2187           dbus_connection_send_preallocated (connection,
2188                                              m->preallocated,
2189                                              m->message,
2190                                              NULL);
2191
2192           m->preallocated = NULL; /* so we don't double-free it */
2193           
2194           message_to_send_free (connection, m);
2195         }
2196         
2197       link = prev;
2198     }
2199 }
2200
2201 void
2202 bus_transaction_execute_and_free (BusTransaction *transaction)
2203 {
2204   /* For each connection in transaction->connections
2205    * send the messages
2206    */
2207   DBusConnection *connection;
2208
2209   _dbus_verbose ("TRANSACTION: executing\n");
2210   
2211   while ((connection = _dbus_list_pop_first (&transaction->connections)))
2212     connection_execute_transaction (connection, transaction);
2213
2214   _dbus_assert (transaction->connections == NULL);
2215
2216   free_cancel_hooks (transaction);
2217   
2218   dbus_free (transaction);
2219 }
2220
2221 static void
2222 bus_connection_remove_transactions (DBusConnection *connection)
2223 {
2224   MessageToSend *to_send;
2225   BusConnectionData *d;
2226   
2227   d = BUS_CONNECTION_DATA (connection);
2228   _dbus_assert (d != NULL);
2229   
2230   while ((to_send = _dbus_list_get_first (&d->transaction_messages)))
2231     {
2232       /* only has an effect for the first MessageToSend listing this transaction */
2233       _dbus_list_remove (&to_send->transaction->connections,
2234                          connection);
2235
2236       _dbus_list_remove (&d->transaction_messages, to_send);
2237       message_to_send_free (connection, to_send);
2238     }
2239 }
2240
2241 /**
2242  * Converts the DBusError to a message reply
2243  */
2244 dbus_bool_t
2245 bus_transaction_send_error_reply (BusTransaction  *transaction,
2246                                   DBusConnection  *connection,
2247                                   const DBusError *error,
2248                                   DBusMessage     *in_reply_to)
2249 {
2250   DBusMessage *reply;
2251   
2252   _dbus_assert (error != NULL);
2253   _DBUS_ASSERT_ERROR_IS_SET (error);
2254   
2255   _dbus_verbose ("Sending error reply %s \"%s\"\n",
2256                  error->name, error->message);
2257
2258   reply = dbus_message_new_error (in_reply_to,
2259                                   error->name,
2260                                   error->message);
2261   if (reply == NULL)
2262     return FALSE;
2263
2264   if (!bus_transaction_send_from_driver (transaction, connection, reply))
2265     {
2266       dbus_message_unref (reply);
2267       return FALSE;
2268     }
2269
2270   dbus_message_unref (reply);
2271   
2272   return TRUE;
2273 }
2274
2275 dbus_bool_t
2276 bus_transaction_add_cancel_hook (BusTransaction               *transaction,
2277                                  BusTransactionCancelFunction  cancel_function,
2278                                  void                         *data,
2279                                  DBusFreeFunction              free_data_function)
2280 {
2281   CancelHook *ch;
2282
2283   ch = dbus_new (CancelHook, 1);
2284   if (ch == NULL)
2285     return FALSE;
2286
2287   _dbus_verbose ("     adding cancel hook function = %p data = %p\n",
2288                  cancel_function, data);
2289   
2290   ch->cancel_function = cancel_function;
2291   ch->data = data;
2292   ch->free_data_function = free_data_function;
2293
2294   /* It's important that the hooks get run in reverse order that they
2295    * were added
2296    */
2297   if (!_dbus_list_prepend (&transaction->cancel_hooks, ch))
2298     {
2299       dbus_free (ch);
2300       return FALSE;
2301     }
2302
2303   return TRUE;
2304 }