/** * 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; }
/** * 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, * and windows_user_function, which may not be safe really. * * @param transport the transport * @returns whether we're authenticated */ dbus_bool_t _dbus_transport_get_is_authenticated (DBusTransport *transport) { if (transport->authenticated) return TRUE; else { dbus_bool_t maybe_authenticated; if (transport->disconnected) return FALSE; /* paranoia ref since we call user callbacks sometimes */ _dbus_connection_ref_unlocked (transport->connection); maybe_authenticated = (!(transport->send_credentials_pending || transport->receive_credentials_pending)); if (maybe_authenticated) { switch (_dbus_auth_do_work (transport->auth)) { case DBUS_AUTH_STATE_AUTHENTICATED: /* leave as maybe_authenticated */ break; default: maybe_authenticated = FALSE; } } /* If we're the client, verify the GUID */ if (maybe_authenticated && !transport->is_server) { const char *server_guid; server_guid = _dbus_auth_get_guid_from_server (transport->auth); _dbus_assert (server_guid != NULL); if (transport->expected_guid && strcmp (transport->expected_guid, server_guid) != 0) { _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; } if (transport->expected_guid == NULL) { transport->expected_guid = _dbus_strdup (server_guid); if (transport->expected_guid == NULL) { _dbus_verbose ("No memory to complete auth in %s\n", _DBUS_FUNCTION_NAME); 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 { allow = auth_via_default_rules (transport); } if (!allow) maybe_authenticated = FALSE; } transport->authenticated = maybe_authenticated; _dbus_connection_unref_unlocked (transport->connection); return maybe_authenticated; } }
/** * 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. * * @param transport the transport * @returns whether we're authenticated */ dbus_bool_t _dbus_transport_get_is_authenticated (DBusTransport *transport) { if (transport->authenticated) return TRUE; else { dbus_bool_t maybe_authenticated; if (transport->disconnected) return FALSE; /* paranoia ref since we call user callbacks sometimes */ _dbus_connection_ref_unlocked (transport->connection); maybe_authenticated = (!(transport->send_credentials_pending || transport->receive_credentials_pending)); if (maybe_authenticated) { switch (_dbus_auth_do_work (transport->auth)) { case DBUS_AUTH_STATE_AUTHENTICATED: /* leave as maybe_authenticated */ break; default: maybe_authenticated = FALSE; } } if (maybe_authenticated && !transport->is_server) { const char *server_guid; server_guid = _dbus_auth_get_guid_from_server (transport->auth); _dbus_assert (server_guid != NULL); if (transport->expected_guid && strcmp (transport->expected_guid, server_guid) != 0) { _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; } if (transport->expected_guid == NULL) { transport->expected_guid = _dbus_strdup (server_guid); if (transport->expected_guid == NULL) { _dbus_verbose ("No memory to complete auth in %s\n", _DBUS_FUNCTION_NAME); return 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 (maybe_authenticated && transport->is_server) { DBusCredentials auth_identity; _dbus_auth_get_identity (transport->auth, &auth_identity); if (transport->unix_user_function != NULL) { 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 ("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; } } 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); } } } transport->authenticated = maybe_authenticated; _dbus_connection_unref_unlocked (transport->connection); return maybe_authenticated; } }