1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-transport.c DBusTransport object (internal to D-Bus implementation)
4 * Copyright (C) 2002, 2003 Red Hat Inc.
6 * Licensed under the Academic Free License version 2.1
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.
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.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "dbus-transport-protected.h"
25 #include "dbus-transport-unix.h"
26 #include "dbus-transport-socket.h"
27 #include "dbus-connection-internal.h"
28 #include "dbus-watch.h"
29 #include "dbus-auth.h"
30 #include "dbus-address.h"
31 #include "dbus-credentials.h"
32 #ifdef DBUS_BUILD_TESTS
33 #include "dbus-server-debug-pipe.h"
37 * @defgroup DBusTransport DBusTransport object
38 * @ingroup DBusInternals
39 * @brief "Backend" for a DBusConnection.
41 * Types and functions related to DBusTransport. A transport is an
42 * abstraction that can send and receive data via various kinds of
43 * network connections or other IPC mechanisms.
49 * @typedef DBusTransport
51 * Opaque object representing a way message stream.
52 * DBusTransport abstracts various kinds of actual
53 * transport mechanism, such as different network protocols,
54 * or encryption schemes.
58 live_messages_size_notify (DBusCounter *counter,
61 DBusTransport *transport = user_data;
63 _dbus_transport_ref (transport);
66 _dbus_verbose ("Counter value is now %d\n",
67 (int) _dbus_counter_get_value (counter));
70 /* disable or re-enable the read watch for the transport if
73 if (transport->vtable->live_messages_changed)
74 (* transport->vtable->live_messages_changed) (transport);
76 _dbus_transport_unref (transport);
80 * Initializes the base class members of DBusTransport. Chained up to
81 * by subclasses in their constructor. The server GUID is the
82 * globally unique ID for the server creating this connection
83 * and will be #NULL for the client side of a connection. The GUID
86 * @param transport the transport being created.
87 * @param vtable the subclass vtable.
88 * @param server_guid non-#NULL if this transport is on the server side of a connection
89 * @param address the address of the transport
90 * @returns #TRUE on success.
93 _dbus_transport_init_base (DBusTransport *transport,
94 const DBusTransportVTable *vtable,
95 const DBusString *server_guid,
96 const DBusString *address)
98 DBusMessageLoader *loader;
100 DBusCounter *counter;
102 DBusCredentials *creds;
104 loader = _dbus_message_loader_new ();
109 auth = _dbus_auth_server_new (server_guid);
111 auth = _dbus_auth_client_new ();
114 _dbus_message_loader_unref (loader);
118 counter = _dbus_counter_new ();
121 _dbus_auth_unref (auth);
122 _dbus_message_loader_unref (loader);
126 creds = _dbus_credentials_new ();
129 _dbus_counter_unref (counter);
130 _dbus_auth_unref (auth);
131 _dbus_message_loader_unref (loader);
137 _dbus_assert (address == NULL);
142 _dbus_assert (address != NULL);
144 if (!_dbus_string_copy_data (address, &address_copy))
146 _dbus_credentials_unref (creds);
147 _dbus_counter_unref (counter);
148 _dbus_auth_unref (auth);
149 _dbus_message_loader_unref (loader);
154 transport->refcount = 1;
155 transport->vtable = vtable;
156 transport->loader = loader;
157 transport->auth = auth;
158 transport->live_messages_size = counter;
159 transport->authenticated = FALSE;
160 transport->disconnected = FALSE;
161 transport->is_server = (server_guid != NULL);
162 transport->send_credentials_pending = !transport->is_server;
163 transport->receive_credentials_pending = transport->is_server;
164 transport->address = address_copy;
166 transport->unix_user_function = NULL;
167 transport->unix_user_data = NULL;
168 transport->free_unix_user_data = NULL;
170 transport->windows_user_function = NULL;
171 transport->windows_user_data = NULL;
172 transport->free_windows_user_data = NULL;
174 transport->expected_guid = NULL;
176 /* Try to default to something that won't totally hose the system,
177 * but doesn't impose too much of a limitation.
179 transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
181 /* credentials read from socket if any */
182 transport->credentials = creds;
184 _dbus_counter_set_notify (transport->live_messages_size,
185 transport->max_live_messages_size,
186 live_messages_size_notify,
189 if (transport->address)
190 _dbus_verbose ("Initialized transport on address %s\n", transport->address);
196 * Finalizes base class members of DBusTransport.
197 * Chained up to from subclass finalizers.
199 * @param transport the transport.
202 _dbus_transport_finalize_base (DBusTransport *transport)
204 if (!transport->disconnected)
205 _dbus_transport_disconnect (transport);
207 if (transport->free_unix_user_data != NULL)
208 (* transport->free_unix_user_data) (transport->unix_user_data);
210 if (transport->free_windows_user_data != NULL)
211 (* transport->free_windows_user_data) (transport->windows_user_data);
213 _dbus_message_loader_unref (transport->loader);
214 _dbus_auth_unref (transport->auth);
215 _dbus_counter_set_notify (transport->live_messages_size,
217 _dbus_counter_unref (transport->live_messages_size);
218 dbus_free (transport->address);
219 dbus_free (transport->expected_guid);
220 if (transport->credentials)
221 _dbus_credentials_unref (transport->credentials);
226 * Verifies if a given D-Bus address is a valid address
227 * by attempting to connect to it. If it is, returns the
228 * opened DBusTransport object. If it isn't, returns #NULL
231 * @param error address where an error can be returned.
232 * @returns a new transport, or #NULL on failure.
234 static DBusTransport*
235 check_address (const char *address, DBusError *error)
237 DBusAddressEntry **entries;
238 DBusTransport *transport = NULL;
241 _dbus_assert (address != NULL);
242 _dbus_assert (*address != '\0');
244 if (!dbus_parse_address (address, &entries, &len, error))
245 return FALSE; /* not a valid address */
247 for (i = 0; i < len; i++)
249 transport = _dbus_transport_open (entries[i], error);
250 if (transport != NULL)
254 dbus_address_entries_free (entries);
259 * Creates a new transport for the "autostart" method.
260 * This creates a client-side of a transport.
262 * @param error address where an error can be returned.
263 * @returns a new transport, or #NULL on failure.
265 static DBusTransport*
266 _dbus_transport_new_for_autolaunch (DBusError *error)
269 DBusTransport *result = NULL;
271 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
273 if (!_dbus_string_init (&address))
275 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
279 if (!_dbus_get_autolaunch_address (&address, error))
281 _DBUS_ASSERT_ERROR_IS_SET (error);
285 result = check_address (_dbus_string_get_const_data (&address), error);
287 _DBUS_ASSERT_ERROR_IS_SET (error);
289 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
292 _dbus_string_free (&address);
296 static DBusTransportOpenResult
297 _dbus_transport_open_autolaunch (DBusAddressEntry *entry,
298 DBusTransport **transport_p,
303 method = dbus_address_entry_get_method (entry);
304 _dbus_assert (method != NULL);
306 if (strcmp (method, "autolaunch") == 0)
308 *transport_p = _dbus_transport_new_for_autolaunch (error);
310 if (*transport_p == NULL)
312 _DBUS_ASSERT_ERROR_IS_SET (error);
313 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
317 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
318 return DBUS_TRANSPORT_OPEN_OK;
323 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
324 return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
328 static const struct {
329 DBusTransportOpenResult (* func) (DBusAddressEntry *entry,
330 DBusTransport **transport_p,
333 { _dbus_transport_open_socket },
334 { _dbus_transport_open_platform_specific },
335 { _dbus_transport_open_autolaunch }
336 #ifdef DBUS_BUILD_TESTS
337 , { _dbus_transport_open_debug_pipe }
342 * Try to open a new transport for the given address entry. (This
343 * opens a client-side-of-the-connection transport.)
345 * @param entry the address entry
346 * @param error location to store reason for failure.
347 * @returns new transport of #NULL on failure.
350 _dbus_transport_open (DBusAddressEntry *entry,
353 DBusTransport *transport;
354 const char *expected_guid_orig;
357 DBusError tmp_error = DBUS_ERROR_INIT;
359 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
362 expected_guid_orig = dbus_address_entry_get_value (entry, "guid");
363 expected_guid = _dbus_strdup (expected_guid_orig);
365 if (expected_guid_orig != NULL && expected_guid == NULL)
367 _DBUS_SET_OOM (error);
371 for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i)
373 DBusTransportOpenResult result;
375 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
376 result = (* open_funcs[i].func) (entry, &transport, &tmp_error);
380 case DBUS_TRANSPORT_OPEN_OK:
381 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
384 case DBUS_TRANSPORT_OPEN_NOT_HANDLED:
385 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
386 /* keep going through the loop of open funcs */
388 case DBUS_TRANSPORT_OPEN_BAD_ADDRESS:
389 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
392 case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT:
393 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
401 if (transport == NULL)
403 if (!dbus_error_is_set (&tmp_error))
404 _dbus_set_bad_address (&tmp_error,
406 "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")");
408 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
409 dbus_move_error(&tmp_error, error);
410 dbus_free (expected_guid);
414 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
416 /* In the case of autostart the initial guid is NULL
417 * and the autostart transport recursively calls
418 * _dbus_open_transport wich returns a transport
419 * with a guid. That guid is the definitive one.
421 * FIXME: if more transports are added they may have
422 * an effect on the expected_guid semantics (i.e.
423 * expected_guid and transport->expected_guid may
424 * both have values). This is very unlikely though
425 * we should either throw asserts here for those
426 * corner cases or refactor the code so it is
427 * clearer on what is expected and what is not
430 transport->expected_guid = expected_guid;
437 * Increments the reference count for the transport.
439 * @param transport the transport.
440 * @returns the transport.
443 _dbus_transport_ref (DBusTransport *transport)
445 _dbus_assert (transport->refcount > 0);
447 transport->refcount += 1;
453 * Decrements the reference count for the transport.
454 * Disconnects and finalizes the transport if
455 * the reference count reaches zero.
457 * @param transport the transport.
460 _dbus_transport_unref (DBusTransport *transport)
462 _dbus_assert (transport != NULL);
463 _dbus_assert (transport->refcount > 0);
465 transport->refcount -= 1;
466 if (transport->refcount == 0)
468 _dbus_verbose ("%s: finalizing\n", _DBUS_FUNCTION_NAME);
470 _dbus_assert (transport->vtable->finalize != NULL);
472 (* transport->vtable->finalize) (transport);
477 * Closes our end of the connection to a remote application. Further
478 * attempts to use this transport will fail. Only the first call to
479 * _dbus_transport_disconnect() will have an effect.
481 * @param transport the transport.
485 _dbus_transport_disconnect (DBusTransport *transport)
487 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
489 _dbus_assert (transport->vtable->disconnect != NULL);
491 if (transport->disconnected)
494 (* transport->vtable->disconnect) (transport);
496 transport->disconnected = TRUE;
498 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
502 * Returns #TRUE if the transport has not been disconnected.
503 * Disconnection can result from _dbus_transport_disconnect()
504 * or because the server drops its end of the connection.
506 * @param transport the transport.
507 * @returns whether we're connected
510 _dbus_transport_get_is_connected (DBusTransport *transport)
512 return !transport->disconnected;
516 auth_via_unix_user_function (DBusTransport *transport)
518 DBusCredentials *auth_identity;
520 DBusConnection *connection;
521 DBusAllowUnixUserFunction unix_user_function;
522 void *unix_user_data;
525 /* Dropping the lock here probably isn't that safe. */
527 auth_identity = _dbus_auth_get_identity (transport->auth);
528 _dbus_assert (auth_identity != NULL);
530 connection = transport->connection;
531 unix_user_function = transport->unix_user_function;
532 unix_user_data = transport->unix_user_data;
533 uid = _dbus_credentials_get_unix_uid (auth_identity);
535 _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME);
536 _dbus_connection_unlock (connection);
538 allow = (* unix_user_function) (connection,
542 _dbus_verbose ("lock %s post unix user function\n", _DBUS_FUNCTION_NAME);
543 _dbus_connection_lock (connection);
547 _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid);
551 _dbus_verbose ("Client UID "DBUS_UID_FORMAT
552 " was rejected, disconnecting\n",
553 _dbus_credentials_get_unix_uid (auth_identity));
554 _dbus_transport_disconnect (transport);
561 auth_via_windows_user_function (DBusTransport *transport)
563 DBusCredentials *auth_identity;
565 DBusConnection *connection;
566 DBusAllowWindowsUserFunction windows_user_function;
567 void *windows_user_data;
570 /* Dropping the lock here probably isn't that safe. */
572 auth_identity = _dbus_auth_get_identity (transport->auth);
573 _dbus_assert (auth_identity != NULL);
575 connection = transport->connection;
576 windows_user_function = transport->windows_user_function;
577 windows_user_data = transport->unix_user_data;
578 windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
580 if (windows_sid == NULL)
586 _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME);
587 _dbus_connection_unlock (connection);
589 allow = (* windows_user_function) (connection,
593 _dbus_verbose ("lock %s post windows user function\n", _DBUS_FUNCTION_NAME);
594 _dbus_connection_lock (connection);
598 _dbus_verbose ("Client SID '%s' authorized\n", windows_sid);
602 _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n",
603 _dbus_credentials_get_windows_sid (auth_identity));
604 _dbus_transport_disconnect (transport);
611 auth_via_default_rules (DBusTransport *transport)
613 DBusCredentials *auth_identity;
614 DBusCredentials *our_identity;
617 auth_identity = _dbus_auth_get_identity (transport->auth);
618 _dbus_assert (auth_identity != NULL);
620 /* By default, connection is allowed if the client is 1) root or 2)
621 * has the same UID as us or 3) anonymous is allowed.
624 our_identity = _dbus_credentials_new_from_current_process ();
625 if (our_identity == NULL)
631 if (transport->allow_anonymous ||
632 _dbus_credentials_get_unix_uid (auth_identity) == 0 ||
633 _dbus_credentials_same_user (our_identity,
636 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
637 _dbus_verbose ("Client authorized as SID '%s'"
638 "matching our SID '%s'\n",
639 _dbus_credentials_get_windows_sid(auth_identity),
640 _dbus_credentials_get_windows_sid(our_identity));
642 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
643 " matching our UID "DBUS_UID_FORMAT"\n",
644 _dbus_credentials_get_unix_uid(auth_identity),
645 _dbus_credentials_get_unix_uid(our_identity));
646 /* We have authenticated! */
651 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
652 _dbus_verbose ("Client authorized as SID '%s'"
653 " but our SID is '%s', disconnecting\n",
654 _dbus_credentials_get_windows_sid(our_identity),
655 _dbus_credentials_get_windows_sid(our_identity));
657 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
658 " but our UID is "DBUS_UID_FORMAT", disconnecting\n",
659 _dbus_credentials_get_unix_uid(our_identity),
660 _dbus_credentials_get_unix_uid(our_identity));
661 _dbus_transport_disconnect (transport);
665 _dbus_credentials_unref (our_identity);
672 * Returns #TRUE if we have been authenticated. Will return #TRUE
673 * even if the transport is disconnected.
675 * @todo we drop connection->mutex when calling the unix_user_function,
676 * and windows_user_function, which may not be safe really.
678 * @param transport the transport
679 * @returns whether we're authenticated
682 _dbus_transport_get_is_authenticated (DBusTransport *transport)
684 if (transport->authenticated)
688 dbus_bool_t maybe_authenticated;
690 if (transport->disconnected)
693 /* paranoia ref since we call user callbacks sometimes */
694 _dbus_connection_ref_unlocked (transport->connection);
696 maybe_authenticated =
697 (!(transport->send_credentials_pending ||
698 transport->receive_credentials_pending));
700 if (maybe_authenticated)
702 switch (_dbus_auth_do_work (transport->auth))
704 case DBUS_AUTH_STATE_AUTHENTICATED:
705 /* leave as maybe_authenticated */
708 maybe_authenticated = FALSE;
712 /* If we're the client, verify the GUID
714 if (maybe_authenticated && !transport->is_server)
716 const char *server_guid;
718 server_guid = _dbus_auth_get_guid_from_server (transport->auth);
719 _dbus_assert (server_guid != NULL);
721 if (transport->expected_guid &&
722 strcmp (transport->expected_guid, server_guid) != 0)
724 _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n",
725 transport->expected_guid, server_guid);
726 _dbus_transport_disconnect (transport);
727 _dbus_connection_unref_unlocked (transport->connection);
731 if (transport->expected_guid == NULL)
733 transport->expected_guid = _dbus_strdup (server_guid);
735 if (transport->expected_guid == NULL)
737 _dbus_verbose ("No memory to complete auth in %s\n", _DBUS_FUNCTION_NAME);
743 /* If we're the server, see if we want to allow this identity to proceed.
745 if (maybe_authenticated && transport->is_server)
748 DBusCredentials *auth_identity;
750 auth_identity = _dbus_auth_get_identity (transport->auth);
751 _dbus_assert (auth_identity != NULL);
753 /* If we have an auth'd user and a user function, delegate
754 * deciding whether auth credentials are good enough to the
755 * app; otherwise, use our default decision process.
757 if (transport->unix_user_function != NULL &&
758 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID))
760 allow = auth_via_unix_user_function (transport);
762 else if (transport->windows_user_function != NULL &&
763 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID))
765 allow = auth_via_windows_user_function (transport);
769 allow = auth_via_default_rules (transport);
773 maybe_authenticated = FALSE;
776 transport->authenticated = maybe_authenticated;
778 _dbus_connection_unref_unlocked (transport->connection);
779 return maybe_authenticated;
784 * See dbus_connection_get_is_anonymous().
786 * @param transport the transport
787 * @returns #TRUE if not authenticated or authenticated as anonymous
790 _dbus_transport_get_is_anonymous (DBusTransport *transport)
792 DBusCredentials *auth_identity;
794 if (!transport->authenticated)
797 auth_identity = _dbus_auth_get_identity (transport->auth);
799 if (_dbus_credentials_are_anonymous (auth_identity))
806 * Gets the address of a transport. It will be
807 * #NULL for a server-side transport.
809 * @param transport the transport
810 * @returns transport's address
813 _dbus_transport_get_address (DBusTransport *transport)
815 return transport->address;
819 * Gets the id of the server we are connected to (see
820 * dbus_server_get_id()). Only works on client side.
822 * @param transport the transport
823 * @returns transport's server's id or #NULL if we are the server side
826 _dbus_transport_get_server_id (DBusTransport *transport)
828 if (transport->is_server)
831 return transport->expected_guid;
835 * Handles a watch by reading data, writing data, or disconnecting
836 * the transport, as appropriate for the given condition.
838 * @param transport the transport.
839 * @param watch the watch.
840 * @param condition the current state of the watched file descriptor.
841 * @returns #FALSE if not enough memory to fully handle the watch
844 _dbus_transport_handle_watch (DBusTransport *transport,
846 unsigned int condition)
850 _dbus_assert (transport->vtable->handle_watch != NULL);
852 if (transport->disconnected)
855 if (dbus_watch_get_socket (watch) < 0)
857 _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n");
861 _dbus_watch_sanitize_condition (watch, &condition);
863 _dbus_transport_ref (transport);
864 _dbus_watch_ref (watch);
865 retval = (* transport->vtable->handle_watch) (transport, watch, condition);
866 _dbus_watch_unref (watch);
867 _dbus_transport_unref (transport);
873 * Sets the connection using this transport. Allows the transport
874 * to add watches to the connection, queue incoming messages,
875 * and pull outgoing messages.
877 * @param transport the transport.
878 * @param connection the connection.
879 * @returns #FALSE if not enough memory
882 _dbus_transport_set_connection (DBusTransport *transport,
883 DBusConnection *connection)
885 _dbus_assert (transport->vtable->connection_set != NULL);
886 _dbus_assert (transport->connection == NULL);
888 transport->connection = connection;
890 _dbus_transport_ref (transport);
891 if (!(* transport->vtable->connection_set) (transport))
892 transport->connection = NULL;
893 _dbus_transport_unref (transport);
895 return transport->connection != NULL;
899 * Get the socket file descriptor, if any.
901 * @param transport the transport
902 * @param fd_p pointer to fill in with the descriptor
903 * @returns #TRUE if a descriptor was available
906 _dbus_transport_get_socket_fd (DBusTransport *transport,
911 if (transport->vtable->get_socket_fd == NULL)
914 if (transport->disconnected)
917 _dbus_transport_ref (transport);
919 retval = (* transport->vtable->get_socket_fd) (transport,
922 _dbus_transport_unref (transport);
928 * Performs a single poll()/select() on the transport's file
929 * descriptors and then reads/writes data as appropriate,
930 * queueing incoming messages and sending outgoing messages.
931 * This is the backend for _dbus_connection_do_iteration().
932 * See _dbus_connection_do_iteration() for full details.
934 * @param transport the transport.
935 * @param flags indicates whether to read or write, and whether to block.
936 * @param timeout_milliseconds if blocking, timeout or -1 for no timeout.
939 _dbus_transport_do_iteration (DBusTransport *transport,
941 int timeout_milliseconds)
943 _dbus_assert (transport->vtable->do_iteration != NULL);
945 _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n",
946 flags, timeout_milliseconds, !transport->disconnected);
948 if ((flags & (DBUS_ITERATION_DO_WRITING |
949 DBUS_ITERATION_DO_READING)) == 0)
950 return; /* Nothing to do */
952 if (transport->disconnected)
955 _dbus_transport_ref (transport);
956 (* transport->vtable->do_iteration) (transport, flags,
957 timeout_milliseconds);
958 _dbus_transport_unref (transport);
960 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
964 recover_unused_bytes (DBusTransport *transport)
966 if (_dbus_auth_needs_decoding (transport->auth))
968 DBusString plaintext;
969 const DBusString *encoded;
973 if (!_dbus_string_init (&plaintext))
976 _dbus_auth_get_unused_bytes (transport->auth,
979 if (!_dbus_auth_decode_data (transport->auth,
980 encoded, &plaintext))
982 _dbus_string_free (&plaintext);
986 _dbus_message_loader_get_buffer (transport->loader,
989 orig_len = _dbus_string_get_length (buffer);
991 if (!_dbus_string_move (&plaintext, 0, buffer,
994 _dbus_string_free (&plaintext);
998 _dbus_verbose (" %d unused bytes sent to message loader\n",
999 _dbus_string_get_length (buffer) -
1002 _dbus_message_loader_return_buffer (transport->loader,
1004 _dbus_string_get_length (buffer) -
1007 _dbus_auth_delete_unused_bytes (transport->auth);
1009 _dbus_string_free (&plaintext);
1013 const DBusString *bytes;
1016 dbus_bool_t succeeded;
1018 _dbus_message_loader_get_buffer (transport->loader,
1021 orig_len = _dbus_string_get_length (buffer);
1023 _dbus_auth_get_unused_bytes (transport->auth,
1027 if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
1030 _dbus_verbose (" %d unused bytes sent to message loader\n",
1031 _dbus_string_get_length (buffer) -
1034 _dbus_message_loader_return_buffer (transport->loader,
1036 _dbus_string_get_length (buffer) -
1040 _dbus_auth_delete_unused_bytes (transport->auth);
1048 _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
1053 * Reports our current dispatch status (whether there's buffered
1054 * data to be queued as messages, or not, or we need memory).
1056 * @param transport the transport
1057 * @returns current status
1060 _dbus_transport_get_dispatch_status (DBusTransport *transport)
1062 if (_dbus_counter_get_value (transport->live_messages_size) >= transport->max_live_messages_size)
1063 return DBUS_DISPATCH_COMPLETE; /* complete for now */
1065 if (!_dbus_transport_get_is_authenticated (transport))
1067 if (_dbus_auth_do_work (transport->auth) ==
1068 DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
1069 return DBUS_DISPATCH_NEED_MEMORY;
1070 else if (!_dbus_transport_get_is_authenticated (transport))
1071 return DBUS_DISPATCH_COMPLETE;
1074 if (!transport->unused_bytes_recovered &&
1075 !recover_unused_bytes (transport))
1076 return DBUS_DISPATCH_NEED_MEMORY;
1078 transport->unused_bytes_recovered = TRUE;
1080 if (!_dbus_message_loader_queue_messages (transport->loader))
1081 return DBUS_DISPATCH_NEED_MEMORY;
1083 if (_dbus_message_loader_peek_message (transport->loader) != NULL)
1084 return DBUS_DISPATCH_DATA_REMAINS;
1086 return DBUS_DISPATCH_COMPLETE;
1090 * Processes data we've read while handling a watch, potentially
1091 * converting some of it to messages and queueing those messages on
1094 * @param transport the transport
1095 * @returns #TRUE if we had enough memory to queue all messages
1098 _dbus_transport_queue_messages (DBusTransport *transport)
1100 DBusDispatchStatus status;
1103 _dbus_verbose ("_dbus_transport_queue_messages()\n");
1106 /* Queue any messages */
1107 while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
1109 DBusMessage *message;
1112 link = _dbus_message_loader_pop_message_link (transport->loader);
1113 _dbus_assert (link != NULL);
1115 message = link->data;
1117 _dbus_verbose ("queueing received message %p\n", message);
1119 if (!_dbus_message_add_size_counter (message, transport->live_messages_size))
1121 _dbus_message_loader_putback_message_link (transport->loader,
1123 status = DBUS_DISPATCH_NEED_MEMORY;
1128 /* pass ownership of link and message ref to connection */
1129 _dbus_connection_queue_received_message_link (transport->connection,
1134 if (_dbus_message_loader_get_is_corrupted (transport->loader))
1136 _dbus_verbose ("Corrupted message stream, disconnecting\n");
1137 _dbus_transport_disconnect (transport);
1140 return status != DBUS_DISPATCH_NEED_MEMORY;
1144 * See dbus_connection_set_max_message_size().
1146 * @param transport the transport
1147 * @param size the max size of a single message
1150 _dbus_transport_set_max_message_size (DBusTransport *transport,
1153 _dbus_message_loader_set_max_message_size (transport->loader, size);
1157 * See dbus_connection_get_max_message_size().
1159 * @param transport the transport
1160 * @returns max message size
1163 _dbus_transport_get_max_message_size (DBusTransport *transport)
1165 return _dbus_message_loader_get_max_message_size (transport->loader);
1169 * See dbus_connection_set_max_received_size().
1171 * @param transport the transport
1172 * @param size the max size of all incoming messages
1175 _dbus_transport_set_max_received_size (DBusTransport *transport,
1178 transport->max_live_messages_size = size;
1179 _dbus_counter_set_notify (transport->live_messages_size,
1180 transport->max_live_messages_size,
1181 live_messages_size_notify,
1187 * See dbus_connection_get_max_received_size().
1189 * @param transport the transport
1190 * @returns max bytes for all live messages
1193 _dbus_transport_get_max_received_size (DBusTransport *transport)
1195 return transport->max_live_messages_size;
1199 * See dbus_connection_get_unix_user().
1201 * @param transport the transport
1202 * @param uid return location for the user ID
1203 * @returns #TRUE if uid is filled in with a valid user ID
1206 _dbus_transport_get_unix_user (DBusTransport *transport,
1209 DBusCredentials *auth_identity;
1211 *uid = _DBUS_INT32_MAX; /* better than some root or system user in
1212 * case of bugs in the caller. Caller should
1213 * never use this value on purpose, however.
1216 if (!transport->authenticated)
1219 auth_identity = _dbus_auth_get_identity (transport->auth);
1221 if (_dbus_credentials_include (auth_identity,
1222 DBUS_CREDENTIAL_UNIX_USER_ID))
1224 *uid = _dbus_credentials_get_unix_uid (auth_identity);
1232 * See dbus_connection_get_unix_process_id().
1234 * @param transport the transport
1235 * @param pid return location for the process ID
1236 * @returns #TRUE if uid is filled in with a valid process ID
1239 _dbus_transport_get_unix_process_id (DBusTransport *transport,
1242 DBusCredentials *auth_identity;
1244 *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose,
1245 * but we set it to a safe number, INT_MAX,
1246 * just to root out possible bugs in bad callers.
1249 if (!transport->authenticated)
1252 auth_identity = _dbus_auth_get_identity (transport->auth);
1254 if (_dbus_credentials_include (auth_identity,
1255 DBUS_CREDENTIAL_UNIX_PROCESS_ID))
1257 *pid = _dbus_credentials_get_unix_pid (auth_identity);
1265 * See dbus_connection_get_adt_audit_session_data().
1267 * @param transport the transport
1268 * @param data return location for the ADT audit data
1269 * @param data_size return length of audit data
1270 * @returns #TRUE if audit data is filled in with a valid ucred
1273 _dbus_transport_get_adt_audit_session_data (DBusTransport *transport,
1277 DBusCredentials *auth_identity;
1282 if (!transport->authenticated)
1285 auth_identity = _dbus_auth_get_identity (transport->auth);
1287 if (_dbus_credentials_include (auth_identity,
1288 DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID))
1290 *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity);
1291 *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity);
1299 * See dbus_connection_set_unix_user_function().
1301 * @param transport the transport
1302 * @param function the predicate
1303 * @param data data to pass to the predicate
1304 * @param free_data_function function to free the data
1305 * @param old_data the old user data to be freed
1306 * @param old_free_data_function old free data function to free it with
1309 _dbus_transport_set_unix_user_function (DBusTransport *transport,
1310 DBusAllowUnixUserFunction function,
1312 DBusFreeFunction free_data_function,
1314 DBusFreeFunction *old_free_data_function)
1316 *old_data = transport->unix_user_data;
1317 *old_free_data_function = transport->free_unix_user_data;
1319 transport->unix_user_function = function;
1320 transport->unix_user_data = data;
1321 transport->free_unix_user_data = free_data_function;
1325 * See dbus_connection_get_windows_user().
1327 * @param transport the transport
1328 * @param windows_sid_p return location for the user ID
1329 * @returns #TRUE if user is available; the returned value may still be #NULL if no memory to copy it
1332 _dbus_transport_get_windows_user (DBusTransport *transport,
1333 char **windows_sid_p)
1335 DBusCredentials *auth_identity;
1337 *windows_sid_p = NULL;
1339 if (!transport->authenticated)
1342 auth_identity = _dbus_auth_get_identity (transport->auth);
1344 if (_dbus_credentials_include (auth_identity,
1345 DBUS_CREDENTIAL_WINDOWS_SID))
1347 /* If no memory, we are supposed to return TRUE and set NULL */
1348 *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
1357 * See dbus_connection_set_windows_user_function().
1359 * @param transport the transport
1360 * @param function the predicate
1361 * @param data data to pass to the predicate
1362 * @param free_data_function function to free the data
1363 * @param old_data the old user data to be freed
1364 * @param old_free_data_function old free data function to free it with
1368 _dbus_transport_set_windows_user_function (DBusTransport *transport,
1369 DBusAllowWindowsUserFunction function,
1371 DBusFreeFunction free_data_function,
1373 DBusFreeFunction *old_free_data_function)
1375 *old_data = transport->windows_user_data;
1376 *old_free_data_function = transport->free_windows_user_data;
1378 transport->windows_user_function = function;
1379 transport->windows_user_data = data;
1380 transport->free_windows_user_data = free_data_function;
1384 * Sets the SASL authentication mechanisms supported by this transport.
1386 * @param transport the transport
1387 * @param mechanisms the #NULL-terminated array of mechanisms
1389 * @returns #FALSE if no memory
1392 _dbus_transport_set_auth_mechanisms (DBusTransport *transport,
1393 const char **mechanisms)
1395 return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
1399 * See dbus_connection_set_allow_anonymous()
1401 * @param transport the transport
1402 * @param value #TRUE to allow anonymous connection
1405 _dbus_transport_set_allow_anonymous (DBusTransport *transport,
1408 transport->allow_anonymous = value != FALSE;