[daemon-fix] Fixed sending daemon match rules for kdbus broadcasts
[platform/upstream/dbus.git] / dbus / dbus-transport.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-transport.c DBusTransport object (internal to D-Bus implementation)
3  *
4  * Copyright (C) 2002, 2003  Red Hat Inc.
5  * Copyright (C) 2013  Samsung Electronics
6  *
7  * Licensed under the Academic Free License version 2.1
8  * 
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24
25
26 #include <../config.h>
27 #include "dbus-transport-protected.h"
28 #include "dbus-transport-unix.h"
29 #include "dbus-transport-socket.h"
30 #include "dbus-connection-internal.h"
31 #include "dbus-watch.h"
32 #include "dbus-auth.h"
33 #include "dbus-address.h"
34 #include "dbus-credentials.h"
35 #include "dbus-mainloop.h"
36 #include "dbus-message.h"
37 #ifdef ENABLE_KDBUS_TRANSPORT
38 #include "dbus-transport-kdbus.h"
39 #endif
40 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
41 #include "dbus-server-debug-pipe.h"
42 #endif
43
44 /**
45  * @defgroup DBusTransport DBusTransport object
46  * @ingroup  DBusInternals
47  * @brief "Backend" for a DBusConnection.
48  *
49  * Types and functions related to DBusTransport.  A transport is an
50  * abstraction that can send and receive data via various kinds of
51  * network connections or other IPC mechanisms.
52  * 
53  * @{
54  */
55
56 /**
57  * @typedef DBusTransport
58  *
59  * Opaque object representing a way message stream.
60  * DBusTransport abstracts various kinds of actual
61  * transport mechanism, such as different network protocols,
62  * or encryption schemes.
63  */
64
65 static void
66 live_messages_notify (DBusCounter *counter,
67                            void        *user_data)
68 {
69   DBusTransport *transport = user_data;
70
71   _dbus_transport_ref (transport);
72
73 #if 0
74   _dbus_verbose ("Size counter value is now %d\n",
75                  (int) _dbus_counter_get_size_value (counter));
76   _dbus_verbose ("Unix FD counter value is now %d\n",
77                  (int) _dbus_counter_get_unix_fd_value (counter));
78 #endif
79
80   /* disable or re-enable the read watch for the transport if
81    * required.
82    */
83   if (transport->vtable->live_messages_changed)
84     {
85       _dbus_connection_lock (transport->connection);
86       (* transport->vtable->live_messages_changed) (transport);
87       _dbus_connection_unlock (transport->connection);
88     }
89
90   _dbus_transport_unref (transport);
91 }
92
93 /**
94  * Initializes the base class members of DBusTransport.  Chained up to
95  * by subclasses in their constructor.  The server GUID is the
96  * globally unique ID for the server creating this connection
97  * and will be #NULL for the client side of a connection. The GUID
98  * is in hex format.
99  *
100  * @param transport the transport being created.
101  * @param vtable the subclass vtable.
102  * @param server_guid non-#NULL if this transport is on the server side of a connection
103  * @param address the address of the transport
104  * @returns #TRUE on success.
105  */
106 dbus_bool_t
107 _dbus_transport_init_base (DBusTransport             *transport,
108                            const DBusTransportVTable *vtable,
109                            const DBusString          *server_guid,
110                            const DBusString          *address)
111 {
112   DBusMessageLoader *loader;
113   DBusAuth *auth;
114   DBusCounter *counter;
115   char *address_copy;
116   DBusCredentials *creds;
117   
118   loader = _dbus_message_loader_new ();
119   if (loader == NULL)
120     return FALSE;
121   
122   if (server_guid)
123     auth = _dbus_auth_server_new (server_guid);
124   else
125   {
126           _dbus_assert (address != NULL);
127           if (!_dbus_string_copy_data (address, &address_copy))
128         {
129           _dbus_message_loader_unref (loader);
130           return FALSE;
131         }
132 #ifdef ENABLE_KDBUS_TRANSPORT
133       if(address_copy == strstr(address_copy, "kdbus:path="))
134           auth = _dbus_auth_client_new_kdbus();
135           else
136 #endif
137                   auth = _dbus_auth_client_new ();
138   }
139
140   if (auth == NULL)
141     {
142       _dbus_message_loader_unref (loader);
143       return FALSE;
144     }
145
146   counter = _dbus_counter_new ();
147   if (counter == NULL)
148     {
149       _dbus_auth_unref (auth);
150       _dbus_message_loader_unref (loader);
151       return FALSE;
152     }  
153
154   creds = _dbus_credentials_new ();
155   if (creds == NULL)
156     {
157       _dbus_counter_unref (counter);
158       _dbus_auth_unref (auth);
159       _dbus_message_loader_unref (loader);
160       return FALSE;
161     }
162   
163   if (server_guid)
164     {
165       _dbus_assert (address == NULL);
166       address_copy = NULL;
167     }
168   
169   transport->refcount = 1;
170   transport->vtable = vtable;
171   transport->loader = loader;
172   transport->auth = auth;
173   transport->live_messages = counter;
174   transport->authenticated = FALSE;
175   transport->disconnected = FALSE;
176   transport->is_server = (server_guid != NULL);
177   transport->send_credentials_pending = !transport->is_server;
178   transport->receive_credentials_pending = transport->is_server;
179   transport->address = address_copy;
180   
181   transport->unix_user_function = NULL;
182   transport->unix_user_data = NULL;
183   transport->free_unix_user_data = NULL;
184
185   transport->windows_user_function = NULL;
186   transport->windows_user_data = NULL;
187   transport->free_windows_user_data = NULL;
188   
189   transport->expected_guid = NULL;
190   
191   /* Try to default to something that won't totally hose the system,
192    * but doesn't impose too much of a limitation.
193    */
194   transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
195
196   /* On Linux RLIMIT_NOFILE defaults to 1024, so allowing 4096 fds live
197      should be more than enough */
198   transport->max_live_messages_unix_fds = 4096;
199
200   /* credentials read from socket if any */
201   transport->credentials = creds;
202
203   _dbus_counter_set_notify (transport->live_messages,
204                             transport->max_live_messages_size,
205                             transport->max_live_messages_unix_fds,
206                             live_messages_notify,
207                             transport);
208
209   if (transport->address)
210     _dbus_verbose ("Initialized transport on address %s\n", transport->address);
211
212   return TRUE;
213 }
214
215 /**
216  * Finalizes base class members of DBusTransport.
217  * Chained up to from subclass finalizers.
218  *
219  * @param transport the transport.
220  */
221 void
222 _dbus_transport_finalize_base (DBusTransport *transport)
223 {
224   if (!transport->disconnected)
225     _dbus_transport_disconnect (transport);
226
227   if (transport->free_unix_user_data != NULL)
228     (* transport->free_unix_user_data) (transport->unix_user_data);
229
230   if (transport->free_windows_user_data != NULL)
231     (* transport->free_windows_user_data) (transport->windows_user_data);
232   
233   _dbus_message_loader_unref (transport->loader);
234   _dbus_auth_unref (transport->auth);
235   _dbus_counter_set_notify (transport->live_messages,
236                             0, 0, NULL, NULL);
237   _dbus_counter_unref (transport->live_messages);
238   dbus_free (transport->address);
239   dbus_free (transport->expected_guid);
240   if (transport->credentials)
241     _dbus_credentials_unref (transport->credentials);
242 }
243
244
245 /**
246  * Verifies if a given D-Bus address is a valid address
247  * by attempting to connect to it. If it is, returns the
248  * opened DBusTransport object. If it isn't, returns #NULL
249  * and sets @p error.
250  *
251  * @param address the address to be checked.
252  * @param error address where an error can be returned.
253  * @returns a new transport, or #NULL on failure.
254  */
255 static DBusTransport*
256 check_address (const char *address, DBusError *error)
257 {
258   DBusAddressEntry **entries;
259   DBusTransport *transport = NULL;
260   int len, i;
261
262   _dbus_assert (address != NULL);
263
264   if (!dbus_parse_address (address, &entries, &len, error))
265     return NULL;              /* not a valid address */
266
267   for (i = 0; i < len; i++)
268     {
269       transport = _dbus_transport_open (entries[i], error);
270       if (transport != NULL)
271         break;
272     }
273
274   dbus_address_entries_free (entries);
275   return transport;
276 }
277
278 /**
279  * Creates a new transport for the "autostart" method.
280  * This creates a client-side of a transport.
281  *
282  * @param scope scope of autolaunch (Windows only)
283  * @param error address where an error can be returned.
284  * @returns a new transport, or #NULL on failure.
285  */
286 static DBusTransport*
287 _dbus_transport_new_for_autolaunch (const char *scope, DBusError *error)
288 {
289   DBusString address;
290   DBusTransport *result = NULL;
291
292   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
293
294   if (!_dbus_string_init (&address))
295     {
296       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
297       return NULL;
298     }
299
300   if (!_dbus_get_autolaunch_address (scope, &address, error))
301     {
302       _DBUS_ASSERT_ERROR_IS_SET (error);
303       goto out;
304     }
305
306   result = check_address (_dbus_string_get_const_data (&address), error);
307   if (result == NULL)
308     _DBUS_ASSERT_ERROR_IS_SET (error);
309   else
310     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
311
312  out:
313   _dbus_string_free (&address);
314   return result;
315 }
316
317 static DBusTransportOpenResult
318 _dbus_transport_open_autolaunch (DBusAddressEntry  *entry,
319                                  DBusTransport    **transport_p,
320                                  DBusError         *error)
321 {
322   const char *method;
323   
324   method = dbus_address_entry_get_method (entry);
325   _dbus_assert (method != NULL);
326
327   if (strcmp (method, "autolaunch") == 0)
328     {
329       const char *scope = dbus_address_entry_get_value (entry, "scope");
330
331       *transport_p = _dbus_transport_new_for_autolaunch (scope, error);
332
333       if (*transport_p == NULL)
334         {
335           _DBUS_ASSERT_ERROR_IS_SET (error);
336           return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
337         }
338       else
339         {
340           _DBUS_ASSERT_ERROR_IS_CLEAR (error);
341           return DBUS_TRANSPORT_OPEN_OK;
342         }      
343     }
344   else
345     {
346       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
347       return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
348     }
349 }
350
351 static const struct {
352   DBusTransportOpenResult (* func) (DBusAddressEntry *entry,
353                                     DBusTransport   **transport_p,
354                                     DBusError        *error);
355 } open_funcs[] = {
356 #ifdef ENABLE_KDBUS_TRANSPORT
357   { _dbus_transport_open_kdbus },
358 #endif
359   { _dbus_transport_open_socket },
360   { _dbus_transport_open_platform_specific },
361   { _dbus_transport_open_autolaunch }
362 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
363   , { _dbus_transport_open_debug_pipe }
364 #endif
365 };
366
367 /**
368  * Try to open a new transport for the given address entry.  (This
369  * opens a client-side-of-the-connection transport.)
370  * 
371  * @param entry the address entry
372  * @param error location to store reason for failure.
373  * @returns new transport of #NULL on failure.
374  */
375 DBusTransport*
376 _dbus_transport_open (DBusAddressEntry *entry,
377                       DBusError        *error)
378 {
379   DBusTransport *transport;
380   const char *expected_guid_orig;
381   char *expected_guid;
382   int i;
383   DBusError tmp_error = DBUS_ERROR_INIT;
384
385   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
386   
387   transport = NULL;
388   expected_guid_orig = dbus_address_entry_get_value (entry, "guid");
389   expected_guid = _dbus_strdup (expected_guid_orig);
390
391   if (expected_guid_orig != NULL && expected_guid == NULL)
392     {
393       _DBUS_SET_OOM (error);
394       return NULL;
395     }
396
397   for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i)
398     {
399       DBusTransportOpenResult result;
400
401       _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
402       result = (* open_funcs[i].func) (entry, &transport, &tmp_error);
403
404       switch (result)
405         {
406         case DBUS_TRANSPORT_OPEN_OK:
407           _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
408           goto out;
409           break;
410         case DBUS_TRANSPORT_OPEN_NOT_HANDLED:
411           _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
412           /* keep going through the loop of open funcs */
413           break;
414         case DBUS_TRANSPORT_OPEN_BAD_ADDRESS:
415           _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
416           goto out;
417           break;
418         case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT:
419           _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
420           goto out;
421           break;
422         }
423     }
424
425  out:
426   
427   if (transport == NULL)
428     {
429       if (!dbus_error_is_set (&tmp_error))
430         _dbus_set_bad_address (&tmp_error,
431                                NULL, NULL,
432                                "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")");
433       
434       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
435       dbus_move_error(&tmp_error, error);
436       dbus_free (expected_guid);
437     }
438   else
439     {
440       _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
441
442       /* In the case of autostart the initial guid is NULL
443        * and the autostart transport recursively calls
444        * _dbus_open_transport wich returns a transport
445        * with a guid.  That guid is the definitive one.
446        *
447        * FIXME: if more transports are added they may have
448        * an effect on the expected_guid semantics (i.e. 
449        * expected_guid and transport->expected_guid may
450        * both have values).  This is very unlikely though
451        * we should either throw asserts here for those 
452        * corner cases or refactor the code so it is 
453        * clearer on what is expected and what is not
454        */
455       if(expected_guid)
456         transport->expected_guid = expected_guid;
457     }
458
459   return transport;
460 }
461
462 /**
463  * Increments the reference count for the transport.
464  *
465  * @param transport the transport.
466  * @returns the transport.
467  */
468 DBusTransport *
469 _dbus_transport_ref (DBusTransport *transport)
470 {
471   _dbus_assert (transport->refcount > 0);
472   
473   transport->refcount += 1;
474
475   return transport;
476 }
477
478 /**
479  * Decrements the reference count for the transport.
480  * Disconnects and finalizes the transport if
481  * the reference count reaches zero.
482  *
483  * @param transport the transport.
484  */
485 void
486 _dbus_transport_unref (DBusTransport *transport)
487 {
488   _dbus_assert (transport != NULL);
489   _dbus_assert (transport->refcount > 0);
490   
491   transport->refcount -= 1;
492   if (transport->refcount == 0)
493     {
494       _dbus_verbose ("finalizing\n");
495       
496       _dbus_assert (transport->vtable->finalize != NULL);
497       
498       (* transport->vtable->finalize) (transport);
499     }
500 }
501
502 /**
503  * Closes our end of the connection to a remote application. Further
504  * attempts to use this transport will fail. Only the first call to
505  * _dbus_transport_disconnect() will have an effect.
506  *
507  * @param transport the transport.
508  * 
509  */
510 void
511 _dbus_transport_disconnect (DBusTransport *transport)
512 {
513   _dbus_verbose ("start\n");
514   
515   _dbus_assert (transport->vtable->disconnect != NULL);
516   
517   if (transport->disconnected)
518     return;
519
520   (* transport->vtable->disconnect) (transport);
521   
522   transport->disconnected = TRUE;
523
524   _dbus_verbose ("end\n");
525 }
526
527 /**
528  * Returns #TRUE if the transport has not been disconnected.
529  * Disconnection can result from _dbus_transport_disconnect()
530  * or because the server drops its end of the connection.
531  *
532  * @param transport the transport.
533  * @returns whether we're connected
534  */
535 dbus_bool_t
536 _dbus_transport_get_is_connected (DBusTransport *transport)
537 {
538   return !transport->disconnected;
539 }
540
541 static dbus_bool_t
542 auth_via_unix_user_function (DBusTransport *transport)
543 {
544   DBusCredentials *auth_identity;
545   dbus_bool_t allow;
546   DBusConnection *connection;
547   DBusAllowUnixUserFunction unix_user_function;
548   void *unix_user_data;
549   dbus_uid_t uid;
550
551   /* Dropping the lock here probably isn't that safe. */
552   
553   auth_identity = _dbus_auth_get_identity (transport->auth);
554   _dbus_assert (auth_identity != NULL);
555
556   connection = transport->connection;
557   unix_user_function = transport->unix_user_function;
558   unix_user_data = transport->unix_user_data;
559   uid = _dbus_credentials_get_unix_uid (auth_identity);
560               
561   _dbus_verbose ("unlock\n");
562   _dbus_connection_unlock (connection);
563
564   allow = (* unix_user_function) (connection,
565                                   uid,
566                                   unix_user_data);
567               
568   _dbus_verbose ("lock post unix user function\n");
569   _dbus_connection_lock (connection);
570
571   if (allow)
572     {
573       _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid);
574     }
575   else
576     {
577       _dbus_verbose ("Client UID "DBUS_UID_FORMAT
578                      " was rejected, disconnecting\n",
579                      _dbus_credentials_get_unix_uid (auth_identity));
580       _dbus_transport_disconnect (transport);
581     }
582
583   return allow;
584 }
585
586 static dbus_bool_t
587 auth_via_windows_user_function (DBusTransport *transport)
588 {
589   DBusCredentials *auth_identity;  
590   dbus_bool_t allow;
591   DBusConnection *connection;
592   DBusAllowWindowsUserFunction windows_user_function;
593   void *windows_user_data;
594   char *windows_sid;
595
596   /* Dropping the lock here probably isn't that safe. */
597   
598   auth_identity = _dbus_auth_get_identity (transport->auth);
599   _dbus_assert (auth_identity != NULL);
600
601   connection = transport->connection;
602   windows_user_function = transport->windows_user_function;
603   windows_user_data = transport->unix_user_data;
604   windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
605
606   if (windows_sid == NULL)
607     {
608       /* OOM */
609       return FALSE;
610     }
611                 
612   _dbus_verbose ("unlock\n");
613   _dbus_connection_unlock (connection);
614
615   allow = (* windows_user_function) (connection,
616                                      windows_sid,
617                                      windows_user_data);
618               
619   _dbus_verbose ("lock post windows user function\n");
620   _dbus_connection_lock (connection);
621
622   if (allow)
623     {
624       _dbus_verbose ("Client SID '%s' authorized\n", windows_sid);
625     }
626   else
627     {
628       _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n",
629                      _dbus_credentials_get_windows_sid (auth_identity));
630       _dbus_transport_disconnect (transport);
631     }
632
633   return allow;
634 }
635
636 static dbus_bool_t
637 auth_via_default_rules (DBusTransport *transport)
638 {
639   DBusCredentials *auth_identity;
640   DBusCredentials *our_identity;
641   dbus_bool_t allow;
642   
643   auth_identity = _dbus_auth_get_identity (transport->auth);
644   _dbus_assert (auth_identity != NULL);
645
646   /* By default, connection is allowed if the client is 1) root or 2)
647    * has the same UID as us or 3) anonymous is allowed.
648    */
649   
650   our_identity = _dbus_credentials_new_from_current_process ();
651   if (our_identity == NULL)
652     {
653       /* OOM */
654       return FALSE;
655     }
656               
657   if (transport->allow_anonymous ||
658       _dbus_credentials_get_unix_uid (auth_identity) == 0 ||
659       _dbus_credentials_same_user (our_identity,
660                                    auth_identity))
661     {
662       if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
663           _dbus_verbose ("Client authorized as SID '%s'"
664                          "matching our SID '%s'\n",
665                          _dbus_credentials_get_windows_sid(auth_identity),
666                          _dbus_credentials_get_windows_sid(our_identity));
667       else
668           _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
669                          " matching our UID "DBUS_UID_FORMAT"\n",
670                          _dbus_credentials_get_unix_uid(auth_identity),
671                          _dbus_credentials_get_unix_uid(our_identity));
672       /* We have authenticated! */
673       allow = TRUE;
674     }
675   else
676     {
677       if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
678           _dbus_verbose ("Client authorized as SID '%s'"
679                          " but our SID is '%s', disconnecting\n",
680                          (_dbus_credentials_get_windows_sid(auth_identity) ?
681                           _dbus_credentials_get_windows_sid(auth_identity) : "<null>"),
682                          (_dbus_credentials_get_windows_sid(our_identity) ?
683                           _dbus_credentials_get_windows_sid(our_identity) : "<null>"));
684       else
685           _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
686                          " but our UID is "DBUS_UID_FORMAT", disconnecting\n",
687                          _dbus_credentials_get_unix_uid(auth_identity),
688                          _dbus_credentials_get_unix_uid(our_identity));
689       _dbus_transport_disconnect (transport);
690       allow = FALSE;
691     }  
692
693   _dbus_credentials_unref (our_identity);
694   
695   return allow;
696 }
697
698 /**
699  * Returns #TRUE if we have been authenticated. It will return #TRUE even if
700  * the transport is now disconnected, but was ever authenticated before
701  * disconnecting.
702  *
703  * This replaces the older _dbus_transport_get_is_authenticated() which
704  * had side-effects.
705  *
706  * @param transport the transport
707  * @returns whether we're authenticated
708  */
709 dbus_bool_t
710 _dbus_transport_peek_is_authenticated (DBusTransport *transport)
711 {
712   return transport->authenticated;
713 }
714
715 /**
716  * Returns #TRUE if we have been authenticated. It will return #TRUE even if
717  * the transport is now disconnected, but was ever authenticated before
718  * disconnecting.
719  *
720  * If we have not finished authenticating, but we have enough buffered input
721  * to finish the job, then this function will do so before it returns.
722  *
723  * This used to be called _dbus_transport_get_is_authenticated(), but that
724  * name seems inappropriate for a function with side-effects.
725  *
726  * @todo we drop connection->mutex when calling the unix_user_function,
727  * and windows_user_function, which may not be safe really.
728  *
729  * @param transport the transport
730  * @returns whether we're authenticated
731  */
732 dbus_bool_t
733 _dbus_transport_try_to_authenticate (DBusTransport *transport)
734 {  
735   if (transport->authenticated)
736     return TRUE;
737   else
738     {
739       dbus_bool_t maybe_authenticated;
740       
741       if (transport->disconnected)
742         return FALSE;
743
744       /* paranoia ref since we call user callbacks sometimes */
745       _dbus_connection_ref_unlocked (transport->connection);
746       
747       maybe_authenticated =
748         (!(transport->send_credentials_pending ||
749            transport->receive_credentials_pending));
750
751       if (maybe_authenticated)
752         {
753           switch (_dbus_auth_do_work (transport->auth))
754             {
755             case DBUS_AUTH_STATE_AUTHENTICATED:
756               /* leave as maybe_authenticated */
757               break;
758             default:
759               maybe_authenticated = FALSE;
760             }
761         }
762
763       /* If we're the client, verify the GUID
764        */
765       if (maybe_authenticated && !transport->is_server)
766         {
767           const char *server_guid;
768
769           server_guid = _dbus_auth_get_guid_from_server (transport->auth);
770           _dbus_assert (server_guid != NULL);
771
772           if (transport->expected_guid &&
773               strcmp (transport->expected_guid, server_guid) != 0)
774             {
775               _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n",
776                              transport->expected_guid, server_guid);
777               _dbus_transport_disconnect (transport);
778               _dbus_connection_unref_unlocked (transport->connection);
779               return FALSE;
780             }
781         }
782
783       /* If we're the server, see if we want to allow this identity to proceed.
784        */
785       if (maybe_authenticated && transport->is_server)
786         {
787           dbus_bool_t allow;
788           DBusCredentials *auth_identity;
789           
790           auth_identity = _dbus_auth_get_identity (transport->auth);
791           _dbus_assert (auth_identity != NULL);
792           
793           /* If we have an auth'd user and a user function, delegate
794            * deciding whether auth credentials are good enough to the
795            * app; otherwise, use our default decision process.
796            */
797           if (transport->unix_user_function != NULL &&
798               _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID))
799             {
800               allow = auth_via_unix_user_function (transport);
801             }
802           else if (transport->windows_user_function != NULL &&
803                    _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID))
804             {
805               allow = auth_via_windows_user_function (transport);
806             }      
807           else
808             {
809               allow = auth_via_default_rules (transport);
810             }
811           
812           if (!allow)
813             maybe_authenticated = FALSE;
814         }
815
816       transport->authenticated = maybe_authenticated;
817
818       _dbus_connection_unref_unlocked (transport->connection);
819       return maybe_authenticated;
820     }
821 }
822
823 /**
824  * See dbus_connection_get_is_anonymous().
825  *
826  * @param transport the transport
827  * @returns #TRUE if not authenticated or authenticated as anonymous
828  */
829 dbus_bool_t
830 _dbus_transport_get_is_anonymous (DBusTransport *transport)
831 {
832   DBusCredentials *auth_identity;
833   
834   if (!transport->authenticated)
835     return TRUE;
836   
837   auth_identity = _dbus_auth_get_identity (transport->auth);
838
839   if (_dbus_credentials_are_anonymous (auth_identity))
840     return TRUE;
841   else
842     return FALSE;
843 }
844
845 /**
846  * Returns TRUE if the transport supports sending unix fds.
847  *
848  * @param transport the transport
849  * @returns #TRUE if TRUE it is possible to send unix fds across the transport.
850  */
851 dbus_bool_t
852 _dbus_transport_can_pass_unix_fd(DBusTransport *transport)
853 {
854   return DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport);
855 }
856
857 /**
858  * Gets the address of a transport. It will be
859  * #NULL for a server-side transport.
860  *
861  * @param transport the transport
862  * @returns transport's address
863  */
864 const char*
865 _dbus_transport_get_address (DBusTransport *transport)
866 {
867   return transport->address;
868 }
869
870 /**
871  * Gets the id of the server we are connected to (see
872  * dbus_server_get_id()). Only works on client side.
873  *
874  * @param transport the transport
875  * @returns transport's server's id or #NULL if we are the server side
876  */
877 const char*
878 _dbus_transport_get_server_id (DBusTransport *transport)
879 {
880   if (transport->is_server)
881     return NULL;
882   else if (transport->authenticated)
883     return _dbus_auth_get_guid_from_server (transport->auth);
884   else
885     return transport->expected_guid;
886 }
887
888 /**
889  * Handles a watch by reading data, writing data, or disconnecting
890  * the transport, as appropriate for the given condition.
891  *
892  * @param transport the transport.
893  * @param watch the watch.
894  * @param condition the current state of the watched file descriptor.
895  * @returns #FALSE if not enough memory to fully handle the watch
896  */
897 dbus_bool_t
898 _dbus_transport_handle_watch (DBusTransport           *transport,
899                               DBusWatch               *watch,
900                               unsigned int             condition)
901 {
902   dbus_bool_t retval;
903   
904   _dbus_assert (transport->vtable->handle_watch != NULL);
905
906   if (transport->disconnected)
907     return TRUE;
908
909   if (dbus_watch_get_socket (watch) < 0)
910     {
911       _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n");
912       return TRUE;
913     }
914   
915   _dbus_watch_sanitize_condition (watch, &condition);
916
917   _dbus_transport_ref (transport);
918   _dbus_watch_ref (watch);
919   retval = (* transport->vtable->handle_watch) (transport, watch, condition);
920   _dbus_watch_unref (watch);
921   _dbus_transport_unref (transport);
922
923   return retval;
924 }
925
926 /**
927  * Sets the connection using this transport. Allows the transport
928  * to add watches to the connection, queue incoming messages,
929  * and pull outgoing messages.
930  *
931  * @param transport the transport.
932  * @param connection the connection.
933  * @returns #FALSE if not enough memory
934  */
935 dbus_bool_t
936 _dbus_transport_set_connection (DBusTransport  *transport,
937                                 DBusConnection *connection)
938 {
939   _dbus_assert (transport->vtable->connection_set != NULL);
940   _dbus_assert (transport->connection == NULL);
941   
942   transport->connection = connection;
943
944   _dbus_transport_ref (transport);
945   if (!(* transport->vtable->connection_set) (transport))
946     transport->connection = NULL;
947   _dbus_transport_unref (transport);
948
949   return transport->connection != NULL;
950 }
951
952 /**
953  * Get the socket file descriptor, if any.
954  *
955  * @param transport the transport
956  * @param fd_p pointer to fill in with the descriptor
957  * @returns #TRUE if a descriptor was available
958  */
959 dbus_bool_t
960 _dbus_transport_get_socket_fd (DBusTransport *transport,
961                                int           *fd_p)
962 {
963   dbus_bool_t retval;
964   
965   if (transport->vtable->get_socket_fd == NULL)
966     return FALSE;
967
968   if (transport->disconnected)
969     return FALSE;
970
971   _dbus_transport_ref (transport);
972
973   retval = (* transport->vtable->get_socket_fd) (transport,
974                                                  fd_p);
975   
976   _dbus_transport_unref (transport);
977
978   return retval;
979 }
980
981 /**
982  * Performs a single poll()/select() on the transport's file
983  * descriptors and then reads/writes data as appropriate,
984  * queueing incoming messages and sending outgoing messages.
985  * This is the backend for _dbus_connection_do_iteration().
986  * See _dbus_connection_do_iteration() for full details.
987  *
988  * @param transport the transport.
989  * @param flags indicates whether to read or write, and whether to block.
990  * @param timeout_milliseconds if blocking, timeout or -1 for no timeout.
991  */
992 void
993 _dbus_transport_do_iteration (DBusTransport  *transport,
994                               unsigned int    flags,
995                               int             timeout_milliseconds)
996 {
997   _dbus_assert (transport->vtable->do_iteration != NULL);
998
999   _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n",
1000                  flags, timeout_milliseconds, !transport->disconnected);
1001   
1002   if ((flags & (DBUS_ITERATION_DO_WRITING |
1003                 DBUS_ITERATION_DO_READING)) == 0)
1004     return; /* Nothing to do */
1005
1006   if (transport->disconnected)
1007     return;
1008
1009   _dbus_transport_ref (transport);
1010   (* transport->vtable->do_iteration) (transport, flags,
1011                                        timeout_milliseconds);
1012   _dbus_transport_unref (transport);
1013
1014   _dbus_verbose ("end\n");
1015 }
1016
1017 static dbus_bool_t
1018 recover_unused_bytes (DBusTransport *transport)
1019 {
1020   if (_dbus_auth_needs_decoding (transport->auth))
1021     {
1022       DBusString plaintext;
1023       const DBusString *encoded;
1024       DBusString *buffer;
1025       int orig_len;
1026
1027       if (!_dbus_string_init (&plaintext))
1028         goto nomem;
1029       
1030       _dbus_auth_get_unused_bytes (transport->auth,
1031                                    &encoded);
1032
1033       if (!_dbus_auth_decode_data (transport->auth,
1034                                    encoded, &plaintext))
1035         {
1036           _dbus_string_free (&plaintext);
1037           goto nomem;
1038         }
1039
1040       _dbus_message_loader_get_buffer (transport->loader,
1041                                        &buffer);
1042       
1043       orig_len = _dbus_string_get_length (buffer);
1044
1045       if (!_dbus_string_move (&plaintext, 0, buffer,
1046                               orig_len))
1047         {
1048           _dbus_string_free (&plaintext);
1049           goto nomem;
1050         }
1051       
1052       _dbus_verbose (" %d unused bytes sent to message loader\n", 
1053                      _dbus_string_get_length (buffer) -
1054                      orig_len);
1055       
1056       _dbus_message_loader_return_buffer (transport->loader,
1057                                           buffer,
1058                                           _dbus_string_get_length (buffer) -
1059                                           orig_len);
1060
1061       _dbus_auth_delete_unused_bytes (transport->auth);
1062       
1063       _dbus_string_free (&plaintext);
1064     }
1065   else
1066     {
1067       const DBusString *bytes;
1068       DBusString *buffer;
1069       int orig_len;
1070       dbus_bool_t succeeded;
1071
1072       _dbus_message_loader_get_buffer (transport->loader,
1073                                        &buffer);
1074                 
1075       orig_len = _dbus_string_get_length (buffer);
1076
1077       _dbus_auth_get_unused_bytes (transport->auth,
1078                                    &bytes);
1079
1080       succeeded = TRUE;
1081       if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
1082         succeeded = FALSE;
1083       
1084       _dbus_verbose (" %d unused bytes sent to message loader\n", 
1085                      _dbus_string_get_length (buffer) -
1086                      orig_len);
1087       
1088       _dbus_message_loader_return_buffer (transport->loader,
1089                                           buffer,
1090                                           _dbus_string_get_length (buffer) -
1091                                           orig_len);
1092
1093       if (succeeded)
1094         _dbus_auth_delete_unused_bytes (transport->auth);
1095       else
1096         goto nomem;
1097     }
1098
1099   return TRUE;
1100
1101  nomem:
1102   _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
1103   return FALSE;
1104 }
1105
1106 /**
1107  * Reports our current dispatch status (whether there's buffered
1108  * data to be queued as messages, or not, or we need memory).
1109  *
1110  * @param transport the transport
1111  * @returns current status
1112  */
1113 DBusDispatchStatus
1114 _dbus_transport_get_dispatch_status (DBusTransport *transport)
1115 {
1116   if (_dbus_counter_get_size_value (transport->live_messages) >= transport->max_live_messages_size ||
1117       _dbus_counter_get_unix_fd_value (transport->live_messages) >= transport->max_live_messages_unix_fds)
1118     return DBUS_DISPATCH_COMPLETE; /* complete for now */
1119
1120   if (!_dbus_transport_try_to_authenticate (transport))
1121     {
1122       if (_dbus_auth_do_work (transport->auth) ==
1123           DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
1124         return DBUS_DISPATCH_NEED_MEMORY;
1125       else if (!_dbus_transport_try_to_authenticate (transport))
1126         return DBUS_DISPATCH_COMPLETE;
1127     }
1128
1129   if (!transport->unused_bytes_recovered &&
1130       !recover_unused_bytes (transport))
1131     return DBUS_DISPATCH_NEED_MEMORY;
1132
1133   transport->unused_bytes_recovered = TRUE;
1134   
1135   if (!_dbus_message_loader_queue_messages (transport->loader))
1136     return DBUS_DISPATCH_NEED_MEMORY;
1137
1138   if (_dbus_message_loader_peek_message (transport->loader) != NULL)
1139     return DBUS_DISPATCH_DATA_REMAINS;
1140   else
1141     return DBUS_DISPATCH_COMPLETE;
1142 }
1143
1144 /**
1145  * Processes data we've read while handling a watch, potentially
1146  * converting some of it to messages and queueing those messages on
1147  * the connection.
1148  *
1149  * @param transport the transport
1150  * @returns #TRUE if we had enough memory to queue all messages
1151  */
1152 dbus_bool_t
1153 _dbus_transport_queue_messages (DBusTransport *transport)
1154 {
1155   DBusDispatchStatus status;
1156
1157 #if 0
1158   _dbus_verbose ("_dbus_transport_queue_messages()\n");
1159 #endif
1160   
1161   /* Queue any messages */
1162   while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
1163     {
1164       DBusMessage *message;
1165       DBusList *link;
1166
1167       link = _dbus_message_loader_pop_message_link (transport->loader);
1168       _dbus_assert (link != NULL);
1169       
1170       message = link->data;
1171       
1172       _dbus_verbose ("queueing received message %p\n", message);
1173
1174       if (!_dbus_message_add_counter (message, transport->live_messages))
1175         {
1176           _dbus_message_loader_putback_message_link (transport->loader,
1177                                                      link);
1178           status = DBUS_DISPATCH_NEED_MEMORY;
1179           break;
1180         }
1181       else
1182         {
1183           /* We didn't call the notify function when we added the counter, so
1184            * catch up now. Since we have the connection's lock, it's desirable
1185            * that we bypass the notify function and call this virtual method
1186            * directly. */
1187           if (transport->vtable->live_messages_changed)
1188             (* transport->vtable->live_messages_changed) (transport);
1189
1190           /* pass ownership of link and message ref to connection */
1191           _dbus_connection_queue_received_message_link (transport->connection,
1192                                                         link);
1193         }
1194     }
1195
1196   if (_dbus_message_loader_get_is_corrupted (transport->loader))
1197     {
1198       _dbus_verbose ("Corrupted message stream, disconnecting\n");
1199       _dbus_transport_disconnect (transport);
1200     }
1201
1202   return status != DBUS_DISPATCH_NEED_MEMORY;
1203 }
1204
1205 /**
1206  * See dbus_connection_set_max_message_size().
1207  *
1208  * @param transport the transport
1209  * @param size the max size of a single message
1210  */
1211 void
1212 _dbus_transport_set_max_message_size (DBusTransport  *transport,
1213                                       long            size)
1214 {
1215   _dbus_message_loader_set_max_message_size (transport->loader, size);
1216 }
1217
1218 /**
1219  * See dbus_connection_set_max_message_unix_fds().
1220  *
1221  * @param transport the transport
1222  * @param n the max number of unix fds of a single message
1223  */
1224 void
1225 _dbus_transport_set_max_message_unix_fds (DBusTransport  *transport,
1226                                           long            n)
1227 {
1228   _dbus_message_loader_set_max_message_unix_fds (transport->loader, n);
1229 }
1230
1231 /**
1232  * See dbus_connection_get_max_message_size().
1233  *
1234  * @param transport the transport
1235  * @returns max message size
1236  */
1237 long
1238 _dbus_transport_get_max_message_size (DBusTransport  *transport)
1239 {
1240   return _dbus_message_loader_get_max_message_size (transport->loader);
1241 }
1242
1243 /**
1244  * See dbus_connection_get_max_message_unix_fds().
1245  *
1246  * @param transport the transport
1247  * @returns max message unix fds
1248  */
1249 long
1250 _dbus_transport_get_max_message_unix_fds (DBusTransport  *transport)
1251 {
1252   return _dbus_message_loader_get_max_message_unix_fds (transport->loader);
1253 }
1254
1255 /**
1256  * See dbus_connection_set_max_received_size().
1257  *
1258  * @param transport the transport
1259  * @param size the max size of all incoming messages
1260  */
1261 void
1262 _dbus_transport_set_max_received_size (DBusTransport  *transport,
1263                                        long            size)
1264 {
1265   transport->max_live_messages_size = size;
1266   _dbus_counter_set_notify (transport->live_messages,
1267                             transport->max_live_messages_size,
1268                             transport->max_live_messages_unix_fds,
1269                             live_messages_notify,
1270                             transport);
1271 }
1272
1273 /**
1274  * See dbus_connection_set_max_received_unix_fds().
1275  *
1276  * @param transport the transport
1277  * @param n the max unix fds of all incoming messages
1278  */
1279 void
1280 _dbus_transport_set_max_received_unix_fds (DBusTransport  *transport,
1281                                            long            n)
1282 {
1283   transport->max_live_messages_unix_fds = n;
1284   _dbus_counter_set_notify (transport->live_messages,
1285                             transport->max_live_messages_size,
1286                             transport->max_live_messages_unix_fds,
1287                             live_messages_notify,
1288                             transport);
1289 }
1290
1291 /**
1292  * See dbus_connection_get_max_received_size().
1293  *
1294  * @param transport the transport
1295  * @returns max bytes for all live messages
1296  */
1297 long
1298 _dbus_transport_get_max_received_size (DBusTransport  *transport)
1299 {
1300   return transport->max_live_messages_size;
1301 }
1302
1303 /**
1304  * See dbus_connection_set_max_received_unix_fds().
1305  *
1306  * @param transport the transport
1307  * @returns max unix fds for all live messages
1308  */
1309 long
1310 _dbus_transport_get_max_received_unix_fds (DBusTransport  *transport)
1311 {
1312   return transport->max_live_messages_unix_fds;
1313 }
1314
1315 /**
1316  * See dbus_connection_get_unix_user().
1317  *
1318  * @param transport the transport
1319  * @param uid return location for the user ID
1320  * @returns #TRUE if uid is filled in with a valid user ID
1321  */
1322 dbus_bool_t
1323 _dbus_transport_get_unix_user (DBusTransport *transport,
1324                                unsigned long *uid)
1325 {
1326   DBusCredentials *auth_identity;
1327
1328   *uid = _DBUS_INT32_MAX; /* better than some root or system user in
1329                            * case of bugs in the caller. Caller should
1330                            * never use this value on purpose, however.
1331                            */
1332   
1333   if (!transport->authenticated)
1334     return FALSE;
1335   
1336   auth_identity = _dbus_auth_get_identity (transport->auth);
1337
1338   if (_dbus_credentials_include (auth_identity,
1339                                  DBUS_CREDENTIAL_UNIX_USER_ID))
1340     {
1341       *uid = _dbus_credentials_get_unix_uid (auth_identity);
1342       return TRUE;
1343     }
1344   else
1345     return FALSE;
1346 }
1347
1348 /**
1349  * See dbus_connection_get_unix_process_id().
1350  *
1351  * @param transport the transport
1352  * @param pid return location for the process ID
1353  * @returns #TRUE if uid is filled in with a valid process ID
1354  */
1355 dbus_bool_t
1356 _dbus_transport_get_unix_process_id (DBusTransport *transport,
1357                                      unsigned long *pid)
1358 {
1359   DBusCredentials *auth_identity;
1360
1361   *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose,
1362                           * but we set it to a safe number, INT_MAX,
1363                           * just to root out possible bugs in bad callers.
1364                           */
1365   
1366   if (!transport->authenticated)
1367     return FALSE;
1368   
1369   auth_identity = _dbus_auth_get_identity (transport->auth);
1370
1371   if (_dbus_credentials_include (auth_identity,
1372                                  DBUS_CREDENTIAL_UNIX_PROCESS_ID))
1373     {
1374       *pid = _dbus_credentials_get_pid (auth_identity);
1375       return TRUE;
1376     }
1377   else
1378     return FALSE;
1379 }
1380
1381 /**
1382  * See dbus_connection_get_adt_audit_session_data().
1383  *
1384  * @param transport the transport
1385  * @param data return location for the ADT audit data 
1386  * @param data_size return length of audit data
1387  * @returns #TRUE if audit data is filled in with a valid ucred
1388  */
1389 dbus_bool_t
1390 _dbus_transport_get_adt_audit_session_data (DBusTransport      *transport,
1391                                             void              **data,
1392                                             int                *data_size)
1393 {
1394   DBusCredentials *auth_identity;
1395
1396   *data = NULL;
1397   *data_size = 0;
1398   
1399   if (!transport->authenticated)
1400     return FALSE;
1401   
1402   auth_identity = _dbus_auth_get_identity (transport->auth);
1403
1404   if (_dbus_credentials_include (auth_identity,
1405                                  DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID))
1406     {
1407       *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity);
1408       *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity);
1409       return TRUE;
1410     }
1411   else
1412     return FALSE;
1413 }
1414
1415 /**
1416  * See dbus_connection_set_unix_user_function().
1417  *
1418  * @param transport the transport
1419  * @param function the predicate
1420  * @param data data to pass to the predicate
1421  * @param free_data_function function to free the data
1422  * @param old_data the old user data to be freed
1423  * @param old_free_data_function old free data function to free it with
1424  */
1425 void
1426 _dbus_transport_set_unix_user_function (DBusTransport             *transport,
1427                                         DBusAllowUnixUserFunction  function,
1428                                         void                      *data,
1429                                         DBusFreeFunction           free_data_function,
1430                                         void                     **old_data,
1431                                         DBusFreeFunction          *old_free_data_function)
1432 {  
1433   *old_data = transport->unix_user_data;
1434   *old_free_data_function = transport->free_unix_user_data;
1435
1436   transport->unix_user_function = function;
1437   transport->unix_user_data = data;
1438   transport->free_unix_user_data = free_data_function;
1439 }
1440
1441 /**
1442  * See dbus_connection_get_windows_user().
1443  *
1444  * @param transport the transport
1445  * @param windows_sid_p return location for the user ID
1446  * @returns #TRUE if user is available; the returned value may still be #NULL if no memory to copy it
1447  */
1448 dbus_bool_t
1449 _dbus_transport_get_windows_user (DBusTransport              *transport,
1450                                   char                      **windows_sid_p)
1451 {
1452   DBusCredentials *auth_identity;
1453
1454   *windows_sid_p = NULL;
1455   
1456   if (!transport->authenticated)
1457     return FALSE;
1458   
1459   auth_identity = _dbus_auth_get_identity (transport->auth);
1460
1461   if (_dbus_credentials_include (auth_identity,
1462                                  DBUS_CREDENTIAL_WINDOWS_SID))
1463     {
1464       /* If no memory, we are supposed to return TRUE and set NULL */
1465       *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
1466
1467       return TRUE;
1468     }
1469   else
1470     return FALSE;
1471 }
1472
1473 /**
1474  * See dbus_connection_set_windows_user_function().
1475  *
1476  * @param transport the transport
1477  * @param function the predicate
1478  * @param data data to pass to the predicate
1479  * @param free_data_function function to free the data
1480  * @param old_data the old user data to be freed
1481  * @param old_free_data_function old free data function to free it with
1482  */
1483
1484 void
1485 _dbus_transport_set_windows_user_function (DBusTransport              *transport,
1486                                            DBusAllowWindowsUserFunction   function,
1487                                            void                       *data,
1488                                            DBusFreeFunction            free_data_function,
1489                                            void                      **old_data,
1490                                            DBusFreeFunction           *old_free_data_function)
1491 {
1492   *old_data = transport->windows_user_data;
1493   *old_free_data_function = transport->free_windows_user_data;
1494
1495   transport->windows_user_function = function;
1496   transport->windows_user_data = data;
1497   transport->free_windows_user_data = free_data_function;
1498 }
1499
1500 /**
1501  * Sets the SASL authentication mechanisms supported by this transport.
1502  *
1503  * @param transport the transport
1504  * @param mechanisms the #NULL-terminated array of mechanisms
1505  *
1506  * @returns #FALSE if no memory
1507  */
1508 dbus_bool_t
1509 _dbus_transport_set_auth_mechanisms (DBusTransport  *transport,
1510                                      const char    **mechanisms)
1511 {
1512   return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
1513 }
1514
1515 /**
1516  * See dbus_connection_set_allow_anonymous()
1517  *
1518  * @param transport the transport
1519  * @param value #TRUE to allow anonymous connection
1520  */
1521 void
1522 _dbus_transport_set_allow_anonymous (DBusTransport              *transport,
1523                                      dbus_bool_t                 value)
1524 {
1525   transport->allow_anonymous = value != FALSE;
1526 }
1527
1528 #ifdef DBUS_ENABLE_STATS
1529 void
1530 _dbus_transport_get_stats (DBusTransport  *transport,
1531                            dbus_uint32_t  *queue_bytes,
1532                            dbus_uint32_t  *queue_fds,
1533                            dbus_uint32_t  *peak_queue_bytes,
1534                            dbus_uint32_t  *peak_queue_fds)
1535 {
1536   if (queue_bytes != NULL)
1537     *queue_bytes = _dbus_counter_get_size_value (transport->live_messages);
1538
1539   if (queue_fds != NULL)
1540     *queue_fds = _dbus_counter_get_unix_fd_value (transport->live_messages);
1541
1542   if (peak_queue_bytes != NULL)
1543     *peak_queue_bytes = _dbus_counter_get_peak_size_value (transport->live_messages);
1544
1545   if (peak_queue_fds != NULL)
1546     *peak_queue_fds = _dbus_counter_get_peak_unix_fd_value (transport->live_messages);
1547 }
1548 #endif /* DBUS_ENABLE_STATS */
1549
1550 /** @} */