diff options
Diffstat (limited to 'src/portal')
-rw-r--r-- | src/portal/meson.build | 1 | ||||
-rw-r--r-- | src/portal/tracker-portal-endpoint.c | 220 | ||||
-rw-r--r-- | src/portal/tracker-portal-endpoint.h | 43 | ||||
-rw-r--r-- | src/portal/tracker-portal.c | 55 |
4 files changed, 313 insertions, 6 deletions
diff --git a/src/portal/meson.build b/src/portal/meson.build index 9b801d975..9304a14cf 100644 --- a/src/portal/meson.build +++ b/src/portal/meson.build @@ -1,6 +1,7 @@ sources = [ 'tracker-main.c', 'tracker-portal.c', + 'tracker-portal-endpoint.c', 'tracker-portal-utils.c', ] diff --git a/src/portal/tracker-portal-endpoint.c b/src/portal/tracker-portal-endpoint.c new file mode 100644 index 000000000..cebd6b590 --- /dev/null +++ b/src/portal/tracker-portal-endpoint.c @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2020, Red Hat Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * Author: Carlos Garnacho <carlosg@gnome.org> + */ +#include "config.h" + +#include <libtracker-sparql/tracker-sparql.h> + +#include "libtracker-sparql/tracker-private.h" + +#include "tracker-portal-endpoint.h" + +typedef struct _TrackerPortalEndpoint TrackerPortalEndpoint; +typedef struct _TrackerPortalEndpointClass TrackerPortalEndpointClass; + +struct _TrackerPortalEndpoint +{ + TrackerEndpointDBus parent_instance; + gchar *peer; + gchar *prologue; + GStrv graphs; +}; + +struct _TrackerPortalEndpointClass +{ + TrackerEndpointDBusClass parent_class; +}; + +enum { + PROP_GRAPHS = 1, + PROP_PEER, + N_PROPS +}; + +static GParamSpec *props[N_PROPS] = { 0 }; + +G_DEFINE_TYPE (TrackerPortalEndpoint, tracker_portal_endpoint, TRACKER_TYPE_ENDPOINT_DBUS) + +static gboolean +tracker_portal_endpoint_forbid_operation (TrackerEndpointDBus *endpoint_dbus, + GDBusMethodInvocation *invocation, + TrackerOperationType operation_type) +{ + TrackerPortalEndpoint *endpoint = TRACKER_PORTAL_ENDPOINT (endpoint_dbus); + + if (operation_type == TRACKER_OPERATION_TYPE_UPDATE) + return TRUE; + if (g_strcmp0 (endpoint->peer, g_dbus_method_invocation_get_sender (invocation)) != 0) + return TRUE; + + return FALSE; +} + +static gboolean +tracker_portal_endpoint_filter_graph (TrackerEndpointDBus *endpoint_dbus, + const gchar *graph_name) +{ + TrackerPortalEndpoint *endpoint = TRACKER_PORTAL_ENDPOINT (endpoint_dbus); + gint i; + + for (i = 0; endpoint->graphs[i]; i++) { + if (g_strcmp0 (graph_name, endpoint->graphs[i]) == 0) { + return FALSE; + } + } + + return TRUE; +} + +static gchar * +tracker_portal_endpoint_add_prologue (TrackerEndpointDBus *endpoint_dbus) +{ + TrackerPortalEndpoint *endpoint = TRACKER_PORTAL_ENDPOINT (endpoint_dbus); + + if (!endpoint->prologue) { + GString *str; + gint i; + + str = g_string_new ("CONSTRAINT SERVICE \n" + "CONSTRAINT GRAPH "); + + for (i = 0; endpoint->graphs[i]; i++) { + if (i != 0) + g_string_append (str, ", "); + + g_string_append_printf (str, "<%s>", endpoint->graphs[i]); + } + + endpoint->prologue = g_string_free (str, FALSE); + } + + return g_strdup (endpoint->prologue); +} + +static void +tracker_portal_endpoint_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + TrackerPortalEndpoint *endpoint = TRACKER_PORTAL_ENDPOINT (object); + + switch (prop_id) { + case PROP_GRAPHS: + endpoint->graphs = g_value_dup_boxed (value); + break; + case PROP_PEER: + endpoint->peer = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +tracker_portal_endpoint_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + TrackerPortalEndpoint *endpoint = TRACKER_PORTAL_ENDPOINT (object); + + switch (prop_id) { + case PROP_GRAPHS: + g_value_set_boxed (value, endpoint->graphs); + break; + case PROP_PEER: + g_value_set_string (value, endpoint->peer); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +tracker_portal_endpoint_finalize (GObject *object) +{ + TrackerPortalEndpoint *endpoint = TRACKER_PORTAL_ENDPOINT (object); + + g_strfreev (endpoint->graphs); + g_free (endpoint->peer); + g_free (endpoint->prologue); + + G_OBJECT_CLASS (tracker_portal_endpoint_parent_class)->finalize (object); +} + +static void +tracker_portal_endpoint_class_init (TrackerPortalEndpointClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + TrackerEndpointDBusClass *endpoint_dbus_class = TRACKER_ENDPOINT_DBUS_CLASS (klass); + + object_class->set_property = tracker_portal_endpoint_set_property; + object_class->get_property = tracker_portal_endpoint_get_property; + object_class->finalize = tracker_portal_endpoint_finalize; + + endpoint_dbus_class->forbid_operation = tracker_portal_endpoint_forbid_operation; + endpoint_dbus_class->filter_graph = tracker_portal_endpoint_filter_graph; + endpoint_dbus_class->add_prologue = tracker_portal_endpoint_add_prologue; + + props[PROP_GRAPHS] = + g_param_spec_boxed ("graphs", + "Graphs", + "Graphs", + G_TYPE_STRV, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + props[PROP_PEER] = + g_param_spec_string ("peer", + "DBus peer", + "DBus peer", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + g_object_class_install_properties (object_class, N_PROPS, props); +} + +static void +tracker_portal_endpoint_init (TrackerPortalEndpoint *portal_endpoint) +{ +} + +TrackerEndpoint * +tracker_portal_endpoint_new (TrackerSparqlConnection *sparql_connection, + GDBusConnection *dbus_connection, + const gchar *object_path, + const gchar *peer, + const gchar * const *graphs, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_fail (TRACKER_IS_SPARQL_CONNECTION (sparql_connection), NULL); + g_return_val_if_fail (G_IS_DBUS_CONNECTION (dbus_connection), NULL); + g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), NULL); + g_return_val_if_fail (!error || !*error, NULL); + + return g_initable_new (TRACKER_TYPE_PORTAL_ENDPOINT, cancellable, error, + "dbus-connection", dbus_connection, + "sparql-connection", sparql_connection, + "object-path", object_path, + "peer", peer, + "graphs", graphs, + NULL); + +} diff --git a/src/portal/tracker-portal-endpoint.h b/src/portal/tracker-portal-endpoint.h new file mode 100644 index 000000000..67b8eee7e --- /dev/null +++ b/src/portal/tracker-portal-endpoint.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020, Red Hat Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * Author: Carlos Garnacho <carlosg@gnome.org> + */ +#ifndef __TRACKER_PORTAL_ENDPOINT_H__ +#define __TRACKER_PORTAL_ENDPOINT_H__ + +#include <gio/gio.h> + +#define TRACKER_TYPE_PORTAL_ENDPOINT tracker_portal_endpoint_get_type () +#define TRACKER_PORTAL_ENDPOINT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_PORTAL_ENDPOINT, TrackerPortalEndpoint)) +#define TRACKER_PORTAL_ENDPOINT_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_PORTAL_ENDPOINT, TrackerPortalEndpointClass)) +#define TRACKER_IS_PORTAL_ENDPOINT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_PORTAL_ENDPOINT)) +#define TRACKER_IS_PORTAL_ENDPOINT_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TRACKER_TYPE_PORTAL_ENDPOINT)) +#define TRACKER_PORTAL_ENDPOINT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_PORTAL_ENDPOINT, TrackerPortalEndpointClass)) + +typedef struct _TrackerPortalEndpoint TrackerPortalEndpoint; + +TrackerEndpoint * tracker_portal_endpoint_new (TrackerSparqlConnection *sparql_connection, + GDBusConnection *dbus_connection, + const gchar *object_path, + const gchar *peer, + const gchar * const *graphs, + GCancellable *cancellable, + GError **error); + +#endif /* __TRACKER_PORTAL_ENDPOINT_H__ */ diff --git a/src/portal/tracker-portal.c b/src/portal/tracker-portal.c index 87c2832e3..15c3ec783 100644 --- a/src/portal/tracker-portal.c +++ b/src/portal/tracker-portal.c @@ -25,6 +25,8 @@ #include <libtracker-common/tracker-common.h> #include "tracker-portal.h" +#include "tracker-portal-endpoint.h" +#include "tracker-portal-utils.h" typedef struct _TrackerPortal TrackerPortal; typedef struct _TrackerSession TrackerSession; @@ -61,6 +63,8 @@ static void tracker_portal_initable_iface_init (GInitableIface *iface); G_DEFINE_TYPE_WITH_CODE (TrackerPortal, tracker_portal, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, tracker_portal_initable_iface_init)) +#define TRACKER_GROUP_NAME "Policy Tracker3" + static const gchar portal_xml[] = "<node>" " <interface name='org.freedesktop.portal.Tracker'>" @@ -168,6 +172,33 @@ tracker_portal_init (TrackerPortal *portal) g_array_set_clear_func (portal->sessions, clear_session); } +static GStrv +load_client_configuration (GDBusMethodInvocation *invocation, + const gchar *service_uri, + GError **error) +{ + g_autoptr (GKeyFile) flatpak_info = NULL; + GStrv graphs; + + flatpak_info = tracker_invocation_lookup_app_info_sync (invocation, + NULL, error); + if (!flatpak_info) { + g_debug ("No .flatpak-info found, forbidden access."); + return NULL; + } + + graphs = g_key_file_get_string_list (flatpak_info, + TRACKER_GROUP_NAME, + service_uri, + NULL, error); + if (!graphs) { + g_debug ("Service '%s' not found in Tracker policy", service_uri); + return NULL; + } + + return graphs; +} + static void portal_iface_method_call (GDBusConnection *connection, const gchar *sender, @@ -189,12 +220,21 @@ portal_iface_method_call (GDBusConnection *connection, g_autoptr(TrackerSparqlConnection) connection = NULL; g_autoptr(TrackerEndpoint) endpoint = NULL; g_autoptr(GError) error = NULL; + g_auto(GStrv) graphs = NULL; + const gchar *sender; GBusType bus_type; TrackerSession session; g_variant_get (parameters, "(s)", &uri); g_debug ("Creating session for service URI '%s'", uri); + graphs = load_client_configuration (invocation, uri, &error); + if (!graphs) { + g_debug ("Session rejected by policy"); + g_dbus_method_invocation_return_gerror (invocation, error); + return; + } + if (!tracker_util_parse_dbus_uri (uri, &bus_type, &service, @@ -224,12 +264,15 @@ portal_iface_method_call (GDBusConnection *connection, session_object_path = g_strdup_printf ("/org/freedesktop/portal/Tracker/Session_%" G_GUINT64_FORMAT, portal->session_ids++); - - endpoint = TRACKER_ENDPOINT (tracker_endpoint_dbus_new (connection, - dbus_connection, - session_object_path, - NULL, - &error)); + sender = g_dbus_method_invocation_get_sender (invocation); + + endpoint = tracker_portal_endpoint_new (connection, + dbus_connection, + session_object_path, + sender, + (const gchar * const *) graphs, + NULL, + &error); if (!endpoint) { g_debug ("Could not create endpoint"); g_dbus_method_invocation_return_gerror (invocation, error); |