static void pid_query_result(DBusPendingCall *pend, void *user_data) { char path[32]; struct access_check *check = user_data; DBusMessage *reply = NULL; DBusMessageIter iter; dbus_uint32_t pid; struct stat st; guint name_watch; DBG("query for busname %s", check->busname); reply = dbus_pending_call_steal_reply(pend); if (!reply) goto done; if (!gid_hash) goto done; if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) goto done; if (g_strcmp0(dbus_message_get_signature(reply), "u")) goto done; dbus_message_iter_init(reply, &iter); dbus_message_iter_get_basic(&iter, &pid); snprintf(path, sizeof(path), "/proc/%u", pid); if (stat(path, &st) < 0) goto done; DBG("query done, pid %d has gid %d", pid, st.st_gid); name_watch = g_dbus_add_disconnect_watch(check->connection, check->busname, busname_exit_callback, g_strdup(check->busname), g_free); g_hash_table_replace(watch_hash, g_strdup(check->busname), GUINT_TO_POINTER(name_watch)); g_hash_table_replace(gid_hash, g_strdup(check->busname), GINT_TO_POINTER(st.st_gid)); if (gid_is_authorized(st.st_gid)) { DBG("allowing access for pid %d, pending %u", pid, check->pending); g_dbus_pending_success(check->connection, check->pending); check->pending_unanswered = FALSE; } done: if (reply) dbus_message_unref(reply); dbus_pending_call_unref(pend); }
static void builtin_security_result(dbus_bool_t authorized, void *user_data) { struct builtin_security_data *data = user_data; if (authorized == TRUE) g_dbus_pending_success(data->conn, data->pending); else g_dbus_pending_error(data->conn, data->pending, DBUS_ERROR_AUTH_FAILED, NULL); g_free(data); }
static void jolla_dbus_access_check(DBusConnection *connection, DBusMessage *message, const char *action, gboolean interaction, GDBusPendingReply pending) { struct access_check *check = NULL; DBusMessage *query = NULL; DBusPendingCall *pend = NULL; const char *busname = dbus_message_get_sender(message); gpointer p; if (!busname) goto fail; if (!authorized_gids) { DBG("No authorization configuration, allowing busname '%s'", busname); g_dbus_pending_success(connection, pending); return; } if (g_hash_table_lookup_extended(gid_hash, busname, NULL, &p)) { gid_t gid = GPOINTER_TO_INT(p); DBG("known busname '%s' has gid %d", busname, gid); if (gid_is_authorized(gid)) { DBG("allowing access for known busname '%s', " "pending %u", busname, pending); g_dbus_pending_success(connection, pending); return; } goto fail; } query = dbus_message_new_method_call("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetConnectionUnixProcessID"); if (!query) goto fail; if (!dbus_message_append_args(query, DBUS_TYPE_STRING, &busname, DBUS_TYPE_INVALID)) goto fail; if (!dbus_connection_send_with_reply(connection, query, &pend, -1)) goto fail; check = g_new0(struct access_check, 1); check->busname = g_strdup(busname); check->connection = dbus_connection_ref(connection); check->pending = pending; check->pending_unanswered = TRUE; if (!dbus_pending_call_set_notify(pend, pid_query_result, check, access_check_free)) goto fail; DBG("pid query sent for pending %u", pending); return; fail: if (check) access_check_free(check); if (pend) { dbus_pending_call_cancel(pend); dbus_pending_call_unref(pend); } if (query) dbus_message_unref(query); DBG("rejecting access for pending %u", pending); g_dbus_pending_error(connection, pending, DBUS_ERROR_AUTH_FAILED, NULL); }