X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dbus%2Fdbus-transport.c;h=3cbe7998cbd6eeb85ae144c2586ce1d78c465d50;hb=2121ff07d5e180e5537418c8d0e69d59eafefdfc;hp=b271d9440bd004bb38d185e95eee95b621ae1a02;hpb=ee27481d7b7d6d9a4f41b7d641a2618dedf676dd;p=platform%2Fupstream%2Fdbus.git diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index b271d94..3cbe799 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -1,5 +1,5 @@ -/* -*- mode: C; c-file-style: "gnu" -*- */ -/* dbus-transport.c DBusTransport object (internal to D-BUS implementation) +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* dbus-transport.c DBusTransport object (internal to D-Bus implementation) * * Copyright (C) 2002, 2003 Red Hat Inc. * @@ -17,16 +17,22 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ +#include #include "dbus-transport-protected.h" #include "dbus-transport-unix.h" +#include "dbus-transport-socket.h" #include "dbus-connection-internal.h" #include "dbus-watch.h" #include "dbus-auth.h" #include "dbus-address.h" +#include "dbus-credentials.h" +#include "dbus-mainloop.h" +#include "dbus-message-private.h" +#include "dbus-marshal-header.h" #ifdef DBUS_BUILD_TESTS #include "dbus-server-debug-pipe.h" #endif @@ -53,7 +59,7 @@ */ static void -live_messages_size_notify (DBusCounter *counter, +live_messages_notify (DBusCounter *counter, void *user_data) { DBusTransport *transport = user_data; @@ -61,14 +67,16 @@ live_messages_size_notify (DBusCounter *counter, _dbus_transport_ref (transport); #if 0 - _dbus_verbose ("Counter value is now %d\n", - (int) _dbus_counter_get_value (counter)); + _dbus_verbose ("Size counter value is now %d\n", + (int) _dbus_counter_get_size_value (counter)); + _dbus_verbose ("Unix FD counter value is now %d\n", + (int) _dbus_counter_get_unix_fd_value (counter)); #endif /* disable or re-enable the read watch for the transport if * required. */ - if (* transport->vtable->live_messages_changed) + if (transport->vtable->live_messages_changed) (* transport->vtable->live_messages_changed) (transport); _dbus_transport_unref (transport); @@ -97,6 +105,7 @@ _dbus_transport_init_base (DBusTransport *transport, DBusAuth *auth; DBusCounter *counter; char *address_copy; + DBusCredentials *creds; loader = _dbus_message_loader_new (); if (loader == NULL) @@ -119,6 +128,15 @@ _dbus_transport_init_base (DBusTransport *transport, _dbus_message_loader_unref (loader); return FALSE; } + + creds = _dbus_credentials_new (); + if (creds == NULL) + { + _dbus_counter_unref (counter); + _dbus_auth_unref (auth); + _dbus_message_loader_unref (loader); + return FALSE; + } if (server_guid) { @@ -131,6 +149,7 @@ _dbus_transport_init_base (DBusTransport *transport, if (!_dbus_string_copy_data (address, &address_copy)) { + _dbus_credentials_unref (creds); _dbus_counter_unref (counter); _dbus_auth_unref (auth); _dbus_message_loader_unref (loader); @@ -142,7 +161,7 @@ _dbus_transport_init_base (DBusTransport *transport, transport->vtable = vtable; transport->loader = loader; transport->auth = auth; - transport->live_messages_size = counter; + transport->live_messages = counter; transport->authenticated = FALSE; transport->disconnected = FALSE; transport->is_server = (server_guid != NULL); @@ -153,24 +172,34 @@ _dbus_transport_init_base (DBusTransport *transport, transport->unix_user_function = NULL; transport->unix_user_data = NULL; transport->free_unix_user_data = NULL; + + transport->windows_user_function = NULL; + transport->windows_user_data = NULL; + transport->free_windows_user_data = NULL; + + transport->expected_guid = NULL; /* Try to default to something that won't totally hose the system, * but doesn't impose too much of a limitation. */ transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63; - - transport->credentials.pid = -1; - transport->credentials.uid = -1; - transport->credentials.gid = -1; - _dbus_counter_set_notify (transport->live_messages_size, + /* On Linux RLIMIT_NOFILE defaults to 1024, so allowing 4096 fds live + should be more than enough */ + transport->max_live_messages_unix_fds = 4096; + + /* credentials read from socket if any */ + transport->credentials = creds; + + _dbus_counter_set_notify (transport->live_messages, transport->max_live_messages_size, - live_messages_size_notify, + transport->max_live_messages_unix_fds, + live_messages_notify, transport); if (transport->address) _dbus_verbose ("Initialized transport on address %s\n", transport->address); - + return TRUE; } @@ -188,15 +217,140 @@ _dbus_transport_finalize_base (DBusTransport *transport) if (transport->free_unix_user_data != NULL) (* transport->free_unix_user_data) (transport->unix_user_data); + + if (transport->free_windows_user_data != NULL) + (* transport->free_windows_user_data) (transport->windows_user_data); _dbus_message_loader_unref (transport->loader); _dbus_auth_unref (transport->auth); - _dbus_counter_set_notify (transport->live_messages_size, - 0, NULL, NULL); - _dbus_counter_unref (transport->live_messages_size); + _dbus_counter_set_notify (transport->live_messages, + 0, 0, NULL, NULL); + _dbus_counter_unref (transport->live_messages); dbus_free (transport->address); + dbus_free (transport->expected_guid); + if (transport->credentials) + _dbus_credentials_unref (transport->credentials); +} + + +/** + * Verifies if a given D-Bus address is a valid address + * by attempting to connect to it. If it is, returns the + * opened DBusTransport object. If it isn't, returns #NULL + * and sets @p error. + * + * @param error address where an error can be returned. + * @returns a new transport, or #NULL on failure. + */ +static DBusTransport* +check_address (const char *address, DBusError *error) +{ + DBusAddressEntry **entries; + DBusTransport *transport = NULL; + int len, i; + + _dbus_assert (address != NULL); + _dbus_assert (*address != '\0'); + + if (!dbus_parse_address (address, &entries, &len, error)) + return NULL; /* not a valid address */ + + for (i = 0; i < len; i++) + { + transport = _dbus_transport_open (entries[i], error); + if (transport != NULL) + break; + } + + dbus_address_entries_free (entries); + return transport; +} + +/** + * Creates a new transport for the "autostart" method. + * This creates a client-side of a transport. + * + * @param error address where an error can be returned. + * @returns a new transport, or #NULL on failure. + */ +static DBusTransport* +_dbus_transport_new_for_autolaunch (const char *scope, DBusError *error) +{ + DBusString address; + DBusTransport *result = NULL; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + if (!_dbus_string_init (&address)) + { + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); + return NULL; + } + + if (!_dbus_get_autolaunch_address (scope, &address, error)) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + goto out; + } + + result = check_address (_dbus_string_get_const_data (&address), error); + if (result == NULL) + _DBUS_ASSERT_ERROR_IS_SET (error); + else + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + out: + _dbus_string_free (&address); + return result; } +static DBusTransportOpenResult +_dbus_transport_open_autolaunch (DBusAddressEntry *entry, + DBusTransport **transport_p, + DBusError *error) +{ + const char *method; + + method = dbus_address_entry_get_method (entry); + _dbus_assert (method != NULL); + + if (strcmp (method, "autolaunch") == 0) + { + const char *scope = dbus_address_entry_get_value (entry, "scope"); + + *transport_p = _dbus_transport_new_for_autolaunch (scope, error); + + if (*transport_p == NULL) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; + } + else + { + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + return DBUS_TRANSPORT_OPEN_OK; + } + } + else + { + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + return DBUS_TRANSPORT_OPEN_NOT_HANDLED; + } +} + +static const struct { + DBusTransportOpenResult (* func) (DBusAddressEntry *entry, + DBusTransport **transport_p, + DBusError *error); +} open_funcs[] = { + { _dbus_transport_open_socket }, + { _dbus_transport_open_platform_specific }, + { _dbus_transport_open_autolaunch } +#ifdef DBUS_BUILD_TESTS + , { _dbus_transport_open_debug_pipe } +#endif +}; + /** * Try to open a new transport for the given address entry. (This * opens a client-side-of-the-connection transport.) @@ -210,117 +364,86 @@ _dbus_transport_open (DBusAddressEntry *entry, DBusError *error) { DBusTransport *transport; - const char *address_problem_type; - const char *address_problem_field; - const char *address_problem_other; - const char *method; + const char *expected_guid_orig; + char *expected_guid; + int i; + DBusError tmp_error = DBUS_ERROR_INIT; _DBUS_ASSERT_ERROR_IS_CLEAR (error); transport = NULL; - address_problem_type = NULL; - address_problem_field = NULL; - address_problem_other = NULL; - - method = dbus_address_entry_get_method (entry); - _dbus_assert (method != NULL); - - if (strcmp (method, "unix") == 0) - { - const char *path = dbus_address_entry_get_value (entry, "path"); - const char *tmpdir = dbus_address_entry_get_value (entry, "tmpdir"); - const char *abstract = dbus_address_entry_get_value (entry, "abstract"); - - if (tmpdir != NULL) - { - address_problem_other = "cannot use the \"tmpdir\" option for an address to connect to, only in an address to listen on"; - goto bad_address; - } - - if (path == NULL && abstract == NULL) - { - address_problem_type = "unix"; - address_problem_field = "path or abstract"; - goto bad_address; - } + expected_guid_orig = dbus_address_entry_get_value (entry, "guid"); + expected_guid = _dbus_strdup (expected_guid_orig); - if (path != NULL && abstract != NULL) - { - address_problem_other = "can't specify both \"path\" and \"abstract\" options in an address"; - goto bad_address; - } - - if (path) - transport = _dbus_transport_new_for_domain_socket (path, FALSE, - error); - else - transport = _dbus_transport_new_for_domain_socket (abstract, TRUE, - error); + if (expected_guid_orig != NULL && expected_guid == NULL) + { + _DBUS_SET_OOM (error); + return NULL; } - else if (strcmp (method, "tcp") == 0) + + for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i) { - const char *host = dbus_address_entry_get_value (entry, "host"); - const char *port = dbus_address_entry_get_value (entry, "port"); - DBusString str; - long lport; - dbus_bool_t sresult; - - if (port == NULL) - { - address_problem_type = "tcp"; - address_problem_field = "port"; - goto bad_address; - } + DBusTransportOpenResult result; - _dbus_string_init_const (&str, port); - sresult = _dbus_string_parse_int (&str, 0, &lport, NULL); - _dbus_string_free (&str); - - if (sresult == FALSE || lport <= 0 || lport > 65535) + _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); + result = (* open_funcs[i].func) (entry, &transport, &tmp_error); + + switch (result) { - address_problem_other = "Port is not an integer between 0 and 65535"; - goto bad_address; + case DBUS_TRANSPORT_OPEN_OK: + _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); + goto out; + break; + case DBUS_TRANSPORT_OPEN_NOT_HANDLED: + _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); + /* keep going through the loop of open funcs */ + break; + case DBUS_TRANSPORT_OPEN_BAD_ADDRESS: + _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); + goto out; + break; + case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT: + _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); + goto out; + break; } - - transport = _dbus_transport_new_for_tcp_socket (host, lport, error); } -#ifdef DBUS_BUILD_TESTS - else if (strcmp (method, "debug-pipe") == 0) - { - const char *name = dbus_address_entry_get_value (entry, "name"); - if (name == NULL) - { - address_problem_type = "debug-pipe"; - address_problem_field = "name"; - goto bad_address; - } - - transport = _dbus_transport_debug_pipe_new (name, error); + out: + + if (transport == NULL) + { + if (!dbus_error_is_set (&tmp_error)) + _dbus_set_bad_address (&tmp_error, + NULL, NULL, + "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")"); + + _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); + dbus_move_error(&tmp_error, error); + dbus_free (expected_guid); } -#endif else { - address_problem_other = "Unknown address type (examples of valid types are \"unix\" and \"tcp\")"; - goto bad_address; + _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); + + /* In the case of autostart the initial guid is NULL + * and the autostart transport recursively calls + * _dbus_open_transport wich returns a transport + * with a guid. That guid is the definitive one. + * + * FIXME: if more transports are added they may have + * an effect on the expected_guid semantics (i.e. + * expected_guid and transport->expected_guid may + * both have values). This is very unlikely though + * we should either throw asserts here for those + * corner cases or refactor the code so it is + * clearer on what is expected and what is not + */ + if(expected_guid) + transport->expected_guid = expected_guid; } - if (transport == NULL) - _DBUS_ASSERT_ERROR_IS_SET (error); - return transport; - - bad_address: - if (address_problem_type != NULL) - dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, - "Address of type %s was missing argument %s", - address_problem_type, address_problem_field); - else - dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, - "Could not parse address: %s", - address_problem_other); - - return NULL; } /** @@ -355,7 +478,7 @@ _dbus_transport_unref (DBusTransport *transport) transport->refcount -= 1; if (transport->refcount == 0) { - _dbus_verbose ("%s: finalizing\n", _DBUS_FUNCTION_NAME); + _dbus_verbose ("finalizing\n"); _dbus_assert (transport->vtable->finalize != NULL); @@ -374,7 +497,7 @@ _dbus_transport_unref (DBusTransport *transport) void _dbus_transport_disconnect (DBusTransport *transport) { - _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME); + _dbus_verbose ("start\n"); _dbus_assert (transport->vtable->disconnect != NULL); @@ -385,7 +508,7 @@ _dbus_transport_disconnect (DBusTransport *transport) transport->disconnected = TRUE; - _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME); + _dbus_verbose ("end\n"); } /** @@ -402,12 +525,170 @@ _dbus_transport_get_is_connected (DBusTransport *transport) return !transport->disconnected; } +static dbus_bool_t +auth_via_unix_user_function (DBusTransport *transport) +{ + DBusCredentials *auth_identity; + dbus_bool_t allow; + DBusConnection *connection; + DBusAllowUnixUserFunction unix_user_function; + void *unix_user_data; + dbus_uid_t uid; + + /* Dropping the lock here probably isn't that safe. */ + + auth_identity = _dbus_auth_get_identity (transport->auth); + _dbus_assert (auth_identity != NULL); + + connection = transport->connection; + unix_user_function = transport->unix_user_function; + unix_user_data = transport->unix_user_data; + uid = _dbus_credentials_get_unix_uid (auth_identity); + + _dbus_verbose ("unlock\n"); + _dbus_connection_unlock (connection); + + allow = (* unix_user_function) (connection, + uid, + unix_user_data); + + _dbus_verbose ("lock post unix user function\n"); + _dbus_connection_lock (connection); + + if (allow) + { + _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid); + } + else + { + _dbus_verbose ("Client UID "DBUS_UID_FORMAT + " was rejected, disconnecting\n", + _dbus_credentials_get_unix_uid (auth_identity)); + _dbus_transport_disconnect (transport); + } + + return allow; +} + +static dbus_bool_t +auth_via_windows_user_function (DBusTransport *transport) +{ + DBusCredentials *auth_identity; + dbus_bool_t allow; + DBusConnection *connection; + DBusAllowWindowsUserFunction windows_user_function; + void *windows_user_data; + char *windows_sid; + + /* Dropping the lock here probably isn't that safe. */ + + auth_identity = _dbus_auth_get_identity (transport->auth); + _dbus_assert (auth_identity != NULL); + + connection = transport->connection; + windows_user_function = transport->windows_user_function; + windows_user_data = transport->unix_user_data; + windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity)); + + if (windows_sid == NULL) + { + /* OOM */ + return FALSE; + } + + _dbus_verbose ("unlock\n"); + _dbus_connection_unlock (connection); + + allow = (* windows_user_function) (connection, + windows_sid, + windows_user_data); + + _dbus_verbose ("lock post windows user function\n"); + _dbus_connection_lock (connection); + + if (allow) + { + _dbus_verbose ("Client SID '%s' authorized\n", windows_sid); + } + else + { + _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n", + _dbus_credentials_get_windows_sid (auth_identity)); + _dbus_transport_disconnect (transport); + } + + return allow; +} + +static dbus_bool_t +auth_via_default_rules (DBusTransport *transport) +{ + DBusCredentials *auth_identity; + DBusCredentials *our_identity; + dbus_bool_t allow; + + auth_identity = _dbus_auth_get_identity (transport->auth); + _dbus_assert (auth_identity != NULL); + + /* By default, connection is allowed if the client is 1) root or 2) + * has the same UID as us or 3) anonymous is allowed. + */ + + our_identity = _dbus_credentials_new_from_current_process (); + if (our_identity == NULL) + { + /* OOM */ + return FALSE; + } + + if (transport->allow_anonymous || + _dbus_credentials_get_unix_uid (auth_identity) == 0 || + _dbus_credentials_same_user (our_identity, + auth_identity)) + { + if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID)) + _dbus_verbose ("Client authorized as SID '%s'" + "matching our SID '%s'\n", + _dbus_credentials_get_windows_sid(auth_identity), + _dbus_credentials_get_windows_sid(our_identity)); + else + _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT + " matching our UID "DBUS_UID_FORMAT"\n", + _dbus_credentials_get_unix_uid(auth_identity), + _dbus_credentials_get_unix_uid(our_identity)); + /* We have authenticated! */ + allow = TRUE; + } + else + { + if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID)) + _dbus_verbose ("Client authorized as SID '%s'" + " but our SID is '%s', disconnecting\n", + (_dbus_credentials_get_windows_sid(auth_identity) ? + _dbus_credentials_get_windows_sid(auth_identity) : ""), + (_dbus_credentials_get_windows_sid(our_identity) ? + _dbus_credentials_get_windows_sid(our_identity) : "")); + else + _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT + " but our UID is "DBUS_UID_FORMAT", disconnecting\n", + _dbus_credentials_get_unix_uid(auth_identity), + _dbus_credentials_get_unix_uid(our_identity)); + _dbus_transport_disconnect (transport); + allow = FALSE; + } + + _dbus_credentials_unref (our_identity); + + return allow; +} + + /** * Returns #TRUE if we have been authenticated. Will return #TRUE * even if the transport is disconnected. * * @todo we drop connection->mutex when calling the unix_user_function, - * which may not be safe really. + * and windows_user_function, which may not be safe really. * * @param transport the transport * @returns whether we're authenticated @@ -442,81 +723,58 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport) maybe_authenticated = FALSE; } } - - /* If we've authenticated as some identity, check that the auth - * identity is the same as our own identity. In the future, we - * may have API allowing applications to specify how this is - * done, for example they may allow connection as any identity, - * but then impose restrictions on certain identities. - * Or they may give certain identities extra privileges. + + /* If we're the client, verify the GUID */ - - if (maybe_authenticated && transport->is_server) + if (maybe_authenticated && !transport->is_server) { - DBusCredentials auth_identity; + const char *server_guid; - _dbus_auth_get_identity (transport->auth, &auth_identity); + server_guid = _dbus_auth_get_guid_from_server (transport->auth); + _dbus_assert (server_guid != NULL); - if (transport->unix_user_function != NULL) + if (transport->expected_guid && + strcmp (transport->expected_guid, server_guid) != 0) { - dbus_bool_t allow; - DBusConnection *connection; - DBusAllowUnixUserFunction unix_user_function; - void *unix_user_data; - - /* Dropping the lock here probably isn't that safe. */ - - connection = transport->connection; - unix_user_function = transport->unix_user_function; - unix_user_data = transport->unix_user_data; + _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n", + transport->expected_guid, server_guid); + _dbus_transport_disconnect (transport); + _dbus_connection_unref_unlocked (transport->connection); + return FALSE; + } + } - _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME); - _dbus_connection_unlock (connection); - - allow = (* unix_user_function) (connection, - auth_identity.uid, - unix_user_data); - - _dbus_verbose ("lock %s post unix user function\n", _DBUS_FUNCTION_NAME); - _dbus_connection_lock (connection); - - if (allow) - { - _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", auth_identity.uid); - } - else - { - _dbus_verbose ("Client UID "DBUS_UID_FORMAT - " was rejected, disconnecting\n", - auth_identity.uid); - _dbus_transport_disconnect (transport); - _dbus_connection_unref_unlocked (connection); - return FALSE; - } + /* If we're the server, see if we want to allow this identity to proceed. + */ + if (maybe_authenticated && transport->is_server) + { + dbus_bool_t allow; + DBusCredentials *auth_identity; + + auth_identity = _dbus_auth_get_identity (transport->auth); + _dbus_assert (auth_identity != NULL); + + /* If we have an auth'd user and a user function, delegate + * deciding whether auth credentials are good enough to the + * app; otherwise, use our default decision process. + */ + if (transport->unix_user_function != NULL && + _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID)) + { + allow = auth_via_unix_user_function (transport); } + else if (transport->windows_user_function != NULL && + _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID)) + { + allow = auth_via_windows_user_function (transport); + } else { - DBusCredentials our_identity; - - _dbus_credentials_from_current_process (&our_identity); - - if (!_dbus_credentials_match (&our_identity, - &auth_identity)) - { - _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT - " but our UID is "DBUS_UID_FORMAT", disconnecting\n", - auth_identity.uid, our_identity.uid); - _dbus_transport_disconnect (transport); - _dbus_connection_unref_unlocked (transport->connection); - return FALSE; - } - else - { - _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT - " matching our UID "DBUS_UID_FORMAT"\n", - auth_identity.uid, our_identity.uid); - } + allow = auth_via_default_rules (transport); } + + if (!allow) + maybe_authenticated = FALSE; } transport->authenticated = maybe_authenticated; @@ -527,6 +785,40 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport) } /** + * See dbus_connection_get_is_anonymous(). + * + * @param transport the transport + * @returns #TRUE if not authenticated or authenticated as anonymous + */ +dbus_bool_t +_dbus_transport_get_is_anonymous (DBusTransport *transport) +{ + DBusCredentials *auth_identity; + + if (!transport->authenticated) + return TRUE; + + auth_identity = _dbus_auth_get_identity (transport->auth); + + if (_dbus_credentials_are_anonymous (auth_identity)) + return TRUE; + else + return FALSE; +} + +/** + * Returns TRUE if the transport supports sending unix fds. + * + * @param transport the transport + * @returns #TRUE if TRUE it is possible to send unix fds across the transport. + */ +dbus_bool_t +_dbus_transport_can_pass_unix_fd(DBusTransport *transport) +{ + return DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport); +} + +/** * Gets the address of a transport. It will be * #NULL for a server-side transport. * @@ -540,6 +832,24 @@ _dbus_transport_get_address (DBusTransport *transport) } /** + * Gets the id of the server we are connected to (see + * dbus_server_get_id()). Only works on client side. + * + * @param transport the transport + * @returns transport's server's id or #NULL if we are the server side + */ +const char* +_dbus_transport_get_server_id (DBusTransport *transport) +{ + if (transport->is_server) + return NULL; + else if (transport->authenticated) + return _dbus_auth_get_guid_from_server (transport->auth); + else + return transport->expected_guid; +} + +/** * Handles a watch by reading data, writing data, or disconnecting * the transport, as appropriate for the given condition. * @@ -560,9 +870,9 @@ _dbus_transport_handle_watch (DBusTransport *transport, if (transport->disconnected) return TRUE; - if (dbus_watch_get_fd (watch) < 0) + if (dbus_watch_get_socket (watch) < 0) { - _dbus_warn ("Tried to handle an invalidated watch; this watch should have been removed\n"); + _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n"); return TRUE; } @@ -604,19 +914,19 @@ _dbus_transport_set_connection (DBusTransport *transport, } /** - * Get the UNIX file descriptor, if any. + * Get the socket file descriptor, if any. * * @param transport the transport * @param fd_p pointer to fill in with the descriptor * @returns #TRUE if a descriptor was available */ dbus_bool_t -_dbus_transport_get_unix_fd (DBusTransport *transport, - int *fd_p) +_dbus_transport_get_socket_fd (DBusTransport *transport, + int *fd_p) { dbus_bool_t retval; - if (transport->vtable->get_unix_fd == NULL) + if (transport->vtable->get_socket_fd == NULL) return FALSE; if (transport->disconnected) @@ -624,8 +934,8 @@ _dbus_transport_get_unix_fd (DBusTransport *transport, _dbus_transport_ref (transport); - retval = (* transport->vtable->get_unix_fd) (transport, - fd_p); + retval = (* transport->vtable->get_socket_fd) (transport, + fd_p); _dbus_transport_unref (transport); @@ -665,7 +975,7 @@ _dbus_transport_do_iteration (DBusTransport *transport, timeout_milliseconds); _dbus_transport_unref (transport); - _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME); + _dbus_verbose ("end\n"); } static dbus_bool_t @@ -767,7 +1077,8 @@ recover_unused_bytes (DBusTransport *transport) DBusDispatchStatus _dbus_transport_get_dispatch_status (DBusTransport *transport) { - if (_dbus_counter_get_value (transport->live_messages_size) >= transport->max_live_messages_size) + if (_dbus_counter_get_size_value (transport->live_messages) >= transport->max_live_messages_size || + _dbus_counter_get_unix_fd_value (transport->live_messages) >= transport->max_live_messages_unix_fds) return DBUS_DISPATCH_COMPLETE; /* complete for now */ if (!_dbus_transport_get_is_authenticated (transport)) @@ -824,7 +1135,7 @@ _dbus_transport_queue_messages (DBusTransport *transport) _dbus_verbose ("queueing received message %p\n", message); - if (!_dbus_message_add_size_counter (message, transport->live_messages_size)) + if (!_dbus_message_add_counter (message, transport->live_messages)) { _dbus_message_loader_putback_message_link (transport->loader, link); @@ -862,6 +1173,19 @@ _dbus_transport_set_max_message_size (DBusTransport *transport, } /** + * See dbus_connection_set_max_message_unix_fds(). + * + * @param transport the transport + * @param n the max number of unix fds of a single message + */ +void +_dbus_transport_set_max_message_unix_fds (DBusTransport *transport, + long n) +{ + _dbus_message_loader_set_max_message_unix_fds (transport->loader, n); +} + +/** * See dbus_connection_get_max_message_size(). * * @param transport the transport @@ -874,6 +1198,18 @@ _dbus_transport_get_max_message_size (DBusTransport *transport) } /** + * See dbus_connection_get_max_message_unix_fds(). + * + * @param transport the transport + * @returns max message unix fds + */ +long +_dbus_transport_get_max_message_unix_fds (DBusTransport *transport) +{ + return _dbus_message_loader_get_max_message_unix_fds (transport->loader); +} + +/** * See dbus_connection_set_max_received_size(). * * @param transport the transport @@ -884,12 +1220,30 @@ _dbus_transport_set_max_received_size (DBusTransport *transport, long size) { transport->max_live_messages_size = size; - _dbus_counter_set_notify (transport->live_messages_size, + _dbus_counter_set_notify (transport->live_messages, transport->max_live_messages_size, - live_messages_size_notify, + transport->max_live_messages_unix_fds, + live_messages_notify, transport); } +/** + * See dbus_connection_set_max_received_unix_fds(). + * + * @param transport the transport + * @param n the max unix fds of all incoming messages + */ +void +_dbus_transport_set_max_received_unix_fds (DBusTransport *transport, + long n) +{ + transport->max_live_messages_unix_fds = n; + _dbus_counter_set_notify (transport->live_messages, + transport->max_live_messages_size, + transport->max_live_messages_unix_fds, + live_messages_notify, + transport); +} /** * See dbus_connection_get_max_received_size(). @@ -904,6 +1258,18 @@ _dbus_transport_get_max_received_size (DBusTransport *transport) } /** + * See dbus_connection_set_max_received_unix_fds(). + * + * @param transport the transport + * @returns max unix fds for all live messages + */ +long +_dbus_transport_get_max_received_unix_fds (DBusTransport *transport) +{ + return transport->max_live_messages_unix_fds; +} + +/** * See dbus_connection_get_unix_user(). * * @param transport the transport @@ -914,7 +1280,7 @@ dbus_bool_t _dbus_transport_get_unix_user (DBusTransport *transport, unsigned long *uid) { - DBusCredentials auth_identity; + DBusCredentials *auth_identity; *uid = _DBUS_INT32_MAX; /* better than some root or system user in * case of bugs in the caller. Caller should @@ -924,11 +1290,12 @@ _dbus_transport_get_unix_user (DBusTransport *transport, if (!transport->authenticated) return FALSE; - _dbus_auth_get_identity (transport->auth, &auth_identity); + auth_identity = _dbus_auth_get_identity (transport->auth); - if (auth_identity.uid != DBUS_UID_UNSET) + if (_dbus_credentials_include (auth_identity, + DBUS_CREDENTIAL_UNIX_USER_ID)) { - *uid = auth_identity.uid; + *uid = _dbus_credentials_get_unix_uid (auth_identity); return TRUE; } else @@ -946,7 +1313,7 @@ dbus_bool_t _dbus_transport_get_unix_process_id (DBusTransport *transport, unsigned long *pid) { - DBusCredentials auth_identity; + DBusCredentials *auth_identity; *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose, * but we set it to a safe number, INT_MAX, @@ -956,11 +1323,46 @@ _dbus_transport_get_unix_process_id (DBusTransport *transport, if (!transport->authenticated) return FALSE; - _dbus_auth_get_identity (transport->auth, &auth_identity); + auth_identity = _dbus_auth_get_identity (transport->auth); - if (auth_identity.pid != DBUS_PID_UNSET) + if (_dbus_credentials_include (auth_identity, + DBUS_CREDENTIAL_UNIX_PROCESS_ID)) { - *pid = auth_identity.pid; + *pid = _dbus_credentials_get_unix_pid (auth_identity); + return TRUE; + } + else + return FALSE; +} + +/** + * See dbus_connection_get_adt_audit_session_data(). + * + * @param transport the transport + * @param data return location for the ADT audit data + * @param data_size return length of audit data + * @returns #TRUE if audit data is filled in with a valid ucred + */ +dbus_bool_t +_dbus_transport_get_adt_audit_session_data (DBusTransport *transport, + void **data, + int *data_size) +{ + DBusCredentials *auth_identity; + + *data = NULL; + *data_size = 0; + + if (!transport->authenticated) + return FALSE; + + auth_identity = _dbus_auth_get_identity (transport->auth); + + if (_dbus_credentials_include (auth_identity, + DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID)) + { + *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity); + *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity); return TRUE; } else @@ -994,6 +1396,65 @@ _dbus_transport_set_unix_user_function (DBusTransport *transport, } /** + * See dbus_connection_get_windows_user(). + * + * @param transport the transport + * @param windows_sid_p return location for the user ID + * @returns #TRUE if user is available; the returned value may still be #NULL if no memory to copy it + */ +dbus_bool_t +_dbus_transport_get_windows_user (DBusTransport *transport, + char **windows_sid_p) +{ + DBusCredentials *auth_identity; + + *windows_sid_p = NULL; + + if (!transport->authenticated) + return FALSE; + + auth_identity = _dbus_auth_get_identity (transport->auth); + + if (_dbus_credentials_include (auth_identity, + DBUS_CREDENTIAL_WINDOWS_SID)) + { + /* If no memory, we are supposed to return TRUE and set NULL */ + *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity)); + + return TRUE; + } + else + return FALSE; +} + +/** + * See dbus_connection_set_windows_user_function(). + * + * @param transport the transport + * @param function the predicate + * @param data data to pass to the predicate + * @param free_data_function function to free the data + * @param old_data the old user data to be freed + * @param old_free_data_function old free data function to free it with + */ + +void +_dbus_transport_set_windows_user_function (DBusTransport *transport, + DBusAllowWindowsUserFunction function, + void *data, + DBusFreeFunction free_data_function, + void **old_data, + DBusFreeFunction *old_free_data_function) +{ + *old_data = transport->windows_user_data; + *old_free_data_function = transport->free_windows_user_data; + + transport->windows_user_function = function; + transport->windows_user_data = data; + transport->free_windows_user_data = free_data_function; +} + +/** * Sets the SASL authentication mechanisms supported by this transport. * * @param transport the transport @@ -1008,5 +1469,39 @@ _dbus_transport_set_auth_mechanisms (DBusTransport *transport, return _dbus_auth_set_mechanisms (transport->auth, mechanisms); } +/** + * See dbus_connection_set_allow_anonymous() + * + * @param transport the transport + * @param value #TRUE to allow anonymous connection + */ +void +_dbus_transport_set_allow_anonymous (DBusTransport *transport, + dbus_bool_t value) +{ + transport->allow_anonymous = value != FALSE; +} + +#ifdef DBUS_ENABLE_STATS +void +_dbus_transport_get_stats (DBusTransport *transport, + dbus_uint32_t *queue_bytes, + dbus_uint32_t *queue_fds, + dbus_uint32_t *peak_queue_bytes, + dbus_uint32_t *peak_queue_fds) +{ + if (queue_bytes != NULL) + *queue_bytes = _dbus_counter_get_size_value (transport->live_messages); + + if (queue_fds != NULL) + *queue_fds = _dbus_counter_get_unix_fd_value (transport->live_messages); + + if (peak_queue_bytes != NULL) + *peak_queue_bytes = _dbus_counter_get_peak_size_value (transport->live_messages); + + if (peak_queue_fds != NULL) + *peak_queue_fds = _dbus_counter_get_peak_unix_fd_value (transport->live_messages); +} +#endif /* DBUS_ENABLE_STATS */ /** @} */