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