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