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