mirror of
https://github.com/flatpak/flatpak.git
synced 2026-10-22 23:55:34 -04:00
dbus-proxy: Add support for filtering on iface/member/path
This adds a new policy level FILTERED which is betweew SEEN and TALK. It implies all that SEEN does, but additionally lets you send method calls to a well known name that matches a filter which can match against interface name, member name and object path. Note: To make the implementation simpler, this does not grant similar access when sending the peer messages via the unique name, only when using the well known name does this work.
This commit is contained in:
1 parent
a8e2dcc1c3
commit
ec902a08fa
3 files changed
+134
-6
No files matched your search
+19
-3
@@ -91,6 +91,7 @@ start_proxy (int n_args, const char *args[])
|
||||
|
||||
if (g_str_has_prefix (args[n], "--see=") ||
|
||||
g_str_has_prefix (args[n], "--talk=") ||
|
||||
g_str_has_prefix (args[n], "--filter=") ||
|
||||
g_str_has_prefix (args[n], "--own="))
|
||||
{
|
||||
FlatpakPolicy policy = FLATPAK_POLICY_SEE;
|
||||
@@ -99,14 +100,29 @@ start_proxy (int n_args, const char *args[])
|
||||
|
||||
if (args[n][2] == 't')
|
||||
policy = FLATPAK_POLICY_TALK;
|
||||
else if (args[n][2] == 'f')
|
||||
policy = FLATPAK_POLICY_FILTERED;
|
||||
else if (args[n][2] == 'o')
|
||||
policy = FLATPAK_POLICY_OWN;
|
||||
|
||||
name = g_strdup (strchr (args[n], '=') + 1);
|
||||
if (g_str_has_suffix (name, ".*"))
|
||||
|
||||
if (policy == FLATPAK_POLICY_FILTERED)
|
||||
{
|
||||
name[strlen (name) - 2] = 0;
|
||||
wildcard = TRUE;
|
||||
char *rule = strchr (name, '=');
|
||||
if (rule != NULL)
|
||||
{
|
||||
*rule++ = 0;
|
||||
flatpak_proxy_add_filter (proxy, name, rule);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g_str_has_suffix (name, ".*"))
|
||||
{
|
||||
name[strlen (name) - 2] = 0;
|
||||
wildcard = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (name[0] == ':' || !g_dbus_is_name (name))
|
||||
|
||||
+111
-3
@@ -73,8 +73,11 @@
|
||||
* You can call the GetXXX methods on the name/id to get e.g. the peer pid
|
||||
* You get AccessDenied rather than NameHasNoOwner when sending messages to the name/id
|
||||
*
|
||||
* FILTERED:
|
||||
* You can send *some* method calls to the name (not id)
|
||||
*
|
||||
* TALK:
|
||||
* You can send method calls and signals to the name/id
|
||||
* You can send any method calls and signals to the name/id
|
||||
* You will receive broadcast signals from the name/id (if you have a match rule for them)
|
||||
* You can call StartServiceByName on the name
|
||||
*
|
||||
@@ -218,6 +221,13 @@ typedef struct
|
||||
guint32 unix_fds;
|
||||
} Header;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *path;
|
||||
char *interface;
|
||||
char *member;
|
||||
} Filter;
|
||||
|
||||
static void header_free (Header *header);
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (Header, header_free)
|
||||
|
||||
@@ -282,6 +292,7 @@ struct FlatpakProxy
|
||||
|
||||
GHashTable *wildcard_policy;
|
||||
GHashTable *policy;
|
||||
GHashTable *filters;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
@@ -468,7 +479,11 @@ flatpak_proxy_add_policy (FlatpakProxy *proxy,
|
||||
const char *name,
|
||||
FlatpakPolicy policy)
|
||||
{
|
||||
g_hash_table_replace (proxy->policy, g_strdup (name), GINT_TO_POINTER (policy));
|
||||
guint current_policy = GPOINTER_TO_INT (g_hash_table_lookup (proxy->policy, name));
|
||||
|
||||
current_policy = MAX (policy, current_policy);
|
||||
|
||||
g_hash_table_replace (proxy->policy, g_strdup (name), GINT_TO_POINTER (current_policy));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -479,6 +494,77 @@ flatpak_proxy_add_wildcarded_policy (FlatpakProxy *proxy,
|
||||
g_hash_table_replace (proxy->wildcard_policy, g_strdup (name), GINT_TO_POINTER (policy));
|
||||
}
|
||||
|
||||
static void
|
||||
filter_free (Filter *filter)
|
||||
{
|
||||
g_free (filter->path);
|
||||
g_free (filter->interface);
|
||||
g_free (filter->member);
|
||||
g_free (filter);
|
||||
}
|
||||
|
||||
static void
|
||||
filter_list_free (GList *filters)
|
||||
{
|
||||
g_list_free_full (filters, (GDestroyNotify)filter_free);
|
||||
}
|
||||
|
||||
/* rules are of the form [org.the.interface.[method|*]][@/obj/path] */
|
||||
static Filter *
|
||||
filter_new (const char *rule)
|
||||
{
|
||||
Filter *filter = g_new0 (Filter, 1);
|
||||
const char *obj_path_start = NULL;
|
||||
const char *method_end = NULL;
|
||||
|
||||
obj_path_start = strchr (rule, '@');
|
||||
if (obj_path_start && obj_path_start[1] != 0)
|
||||
filter->path = g_strdup (obj_path_start + 1);
|
||||
|
||||
if (obj_path_start != NULL)
|
||||
method_end = obj_path_start;
|
||||
else
|
||||
method_end = rule + strlen(rule);
|
||||
|
||||
if (rule[0] != '@')
|
||||
{
|
||||
filter->interface = g_strndup (rule, method_end - rule);
|
||||
char *dot = strrchr (filter->interface, '.');
|
||||
if (dot != NULL)
|
||||
{
|
||||
*dot = 0;
|
||||
if (strcmp (dot+1, "*") != 0)
|
||||
filter->member = g_strdup (dot + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
flatpak_proxy_add_filter (FlatpakProxy *proxy,
|
||||
const char *name,
|
||||
const char *rule)
|
||||
{
|
||||
Filter *filter;
|
||||
GList *filters, *new_filters;
|
||||
|
||||
filter = filter_new (rule);
|
||||
if (g_hash_table_lookup_extended (proxy->filters,
|
||||
name,
|
||||
NULL, (void **)&filters))
|
||||
{
|
||||
new_filters = g_list_append (filters, filter);
|
||||
g_assert (new_filters == filters);
|
||||
}
|
||||
else
|
||||
{
|
||||
filters = g_list_append (NULL, filter);
|
||||
g_hash_table_insert (proxy->filters, g_strdup (name), filters);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
flatpak_proxy_finalize (GObject *object)
|
||||
{
|
||||
@@ -491,6 +577,7 @@ flatpak_proxy_finalize (GObject *object)
|
||||
|
||||
g_hash_table_destroy (proxy->policy);
|
||||
g_hash_table_destroy (proxy->wildcard_policy);
|
||||
g_hash_table_destroy (proxy->filters);
|
||||
|
||||
g_free (proxy->socket_path);
|
||||
g_free (proxy->dbus_address);
|
||||
@@ -1399,9 +1486,29 @@ get_dbus_method_handler (FlatpakProxyClient *client, Header *header)
|
||||
policy = flatpak_proxy_client_get_policy (client, header->destination);
|
||||
if (policy < FLATPAK_POLICY_SEE)
|
||||
return HANDLE_HIDE;
|
||||
if (policy < FLATPAK_POLICY_TALK)
|
||||
if (policy < FLATPAK_POLICY_FILTERED)
|
||||
return HANDLE_DENY;
|
||||
|
||||
if (policy == FLATPAK_POLICY_FILTERED)
|
||||
{
|
||||
GList *filters = NULL, *l;
|
||||
|
||||
if (header->destination)
|
||||
filters = g_hash_table_lookup (client->proxy->filters, header->destination);
|
||||
for (l = filters; l != NULL; l = l->next)
|
||||
{
|
||||
Filter *filter = l->data;
|
||||
|
||||
if (header->type == G_DBUS_MESSAGE_TYPE_METHOD_CALL &&
|
||||
(filter->path == NULL || g_strcmp0 (filter->path, header->path) == 0) &&
|
||||
(filter->interface == NULL || g_strcmp0 (filter->interface, header->interface) == 0) &&
|
||||
(filter->member == NULL || g_strcmp0 (filter->member, header->member) == 0))
|
||||
return HANDLE_PASS;
|
||||
}
|
||||
|
||||
return HANDLE_DENY;
|
||||
}
|
||||
|
||||
if (!is_for_bus (header))
|
||||
return HANDLE_PASS;
|
||||
|
||||
@@ -2419,6 +2526,7 @@ static void
|
||||
flatpak_proxy_init (FlatpakProxy *proxy)
|
||||
{
|
||||
proxy->policy = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
proxy->filters = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)filter_list_free);
|
||||
proxy->wildcard_policy = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
flatpak_proxy_add_policy (proxy, "org.freedesktop.DBus", FLATPAK_POLICY_TALK);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
typedef enum {
|
||||
FLATPAK_POLICY_NONE,
|
||||
FLATPAK_POLICY_SEE,
|
||||
FLATPAK_POLICY_FILTERED,
|
||||
FLATPAK_POLICY_TALK,
|
||||
FLATPAK_POLICY_OWN
|
||||
} FlatpakPolicy;
|
||||
@@ -53,6 +54,9 @@ void flatpak_proxy_add_policy (FlatpakProxy *proxy,
|
||||
void flatpak_proxy_add_wildcarded_policy (FlatpakProxy *proxy,
|
||||
const char *name,
|
||||
FlatpakPolicy policy);
|
||||
void flatpak_proxy_add_filter (FlatpakProxy *proxy,
|
||||
const char *name,
|
||||
const char *rule);
|
||||
gboolean flatpak_proxy_start (FlatpakProxy *proxy,
|
||||
GError **error);
|
||||
void flatpak_proxy_stop (FlatpakProxy *proxy);
|
||||
|
||||
Reference in new issue
Block a user