mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2026-05-09 03:58:05 +02:00
Merge branch 'master' into 'master'
permission-manager: Add core_permissions support See merge request pipewire/wireplumber!822
This commit is contained in:
commit
df848522e0
9 changed files with 159 additions and 2 deletions
|
|
@ -58,3 +58,68 @@ Possible permissions are any combination of:
|
|||
client can't "see" (i.e. the client doesn't have ``r`` permission on them)
|
||||
|
||||
The special value ``all`` is also supported and it is synonym for ``rwxm``
|
||||
|
||||
Permission Managers
|
||||
-------------------
|
||||
|
||||
For more advanced use cases, WirePlumber supports *permission managers* that can
|
||||
apply per-object permissions dynamically based on rules and object interests.
|
||||
Permission managers are defined in the ``access.permission-managers`` section
|
||||
and then referenced by name in ``access.rules``.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block::
|
||||
|
||||
access.permission-managers = [
|
||||
{
|
||||
name = "custom"
|
||||
default_permissions = "all"
|
||||
core_permissions = "rx"
|
||||
rules = [
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
media.class = "Audio/Source"
|
||||
}
|
||||
]
|
||||
actions = {
|
||||
set-permissions = "-"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
access.rules = [
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
application.name = "paplay"
|
||||
}
|
||||
]
|
||||
actions = {
|
||||
update-props = {
|
||||
permission_manager_name = "custom"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
Each permission manager supports the following properties:
|
||||
|
||||
* ``name``: (required) a unique name used to reference the manager from
|
||||
``access.rules``
|
||||
* ``default_permissions``: the fallback permissions applied to all objects
|
||||
that don't match any rule (applied as ``PW_ID_ANY``)
|
||||
* ``core_permissions``: permissions applied specifically to the PipeWire core
|
||||
object (``PW_ID_CORE``, ID 0). This is useful when you want to allow a
|
||||
client to interact with the core (e.g. enumerate objects, subscribe to
|
||||
events) while restricting access to individual objects. If not set, the
|
||||
``default_permissions`` value is used for the core as well.
|
||||
* ``rules``: a list of match rules with ``set-permissions`` actions that
|
||||
grant specific permissions to objects matching the given constraints
|
||||
|
||||
When both ``default_permissions`` and ``permission_manager_name`` are set in
|
||||
a rule's ``update-props`` action, ``default_permissions`` takes precedence and
|
||||
the permission manager is ignored.
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ C API Documentation
|
|||
c_api/link_api.rst
|
||||
c_api/device_api.rst
|
||||
c_api/client_api.rst
|
||||
c_api/permission_manager_api.rst
|
||||
c_api/metadata_api.rst
|
||||
c_api/spa_device_api.rst
|
||||
c_api/impl_node_api.rst
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ sphinx_files += files(
|
|||
'obj_manager_api.rst',
|
||||
'object_api.rst',
|
||||
'pipewire_object_api.rst',
|
||||
'permission_manager_api.rst',
|
||||
'plugin_api.rst',
|
||||
'port_api.rst',
|
||||
'properties_api.rst',
|
||||
|
|
|
|||
17
docs/rst/library/c_api/permission_manager_api.rst
Normal file
17
docs/rst/library/c_api/permission_manager_api.rst
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
.. _permission_manager_api:
|
||||
|
||||
WpPermissionManager
|
||||
===================
|
||||
.. graphviz::
|
||||
:align: center
|
||||
|
||||
digraph inheritance {
|
||||
rankdir=LR;
|
||||
GObject -> WpObject;
|
||||
WpObject -> WpPermissionManager;
|
||||
}
|
||||
|
||||
.. doxygenstruct:: WpPermissionManager
|
||||
|
||||
.. doxygengroup:: wppermissionmanager
|
||||
:content-only:
|
||||
|
|
@ -76,6 +76,7 @@ struct _WpPermissionManager
|
|||
WpObject parent;
|
||||
|
||||
guint32 default_perms;
|
||||
guint32 core_perms;
|
||||
GPtrArray *clients;
|
||||
GHashTable *matches;
|
||||
|
||||
|
|
@ -90,6 +91,9 @@ wp_permission_manager_init (WpPermissionManager * self)
|
|||
/* Init default permissions to all */
|
||||
self->default_perms = PW_PERM_R | PW_PERM_W | PW_PERM_X;
|
||||
|
||||
/* Core permissions not set by default (inherit from default_perms) */
|
||||
self->core_perms = PW_PERM_INVALID;
|
||||
|
||||
/* Init permission interests table */
|
||||
self->matches = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
|
||||
(GDestroyNotify)permission_interest_free);
|
||||
|
|
@ -271,6 +275,13 @@ build_permissions_array (WpPermissionManager *self, WpClient *client)
|
|||
/* Add default permissions */
|
||||
g_array_append_val (arr, def_perm);
|
||||
|
||||
/* Add core permissions if explicitly set (core is not in the OM since it is
|
||||
* implicit in the PipeWire connection and not sent through the registry) */
|
||||
if (self->core_perms != PW_PERM_INVALID) {
|
||||
struct pw_permission core_perm = { PW_ID_CORE, self->core_perms };
|
||||
g_array_append_val (arr, core_perm);
|
||||
}
|
||||
|
||||
/* Add object specific permissions in the array */
|
||||
it = wp_object_manager_new_iterator (self->om);
|
||||
for (; wp_iterator_next (it, &value); g_value_unset (&value)) {
|
||||
|
|
@ -512,6 +523,32 @@ wp_permission_manager_set_default_permissions (WpPermissionManager *self,
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the permissions that will be applied to the core object (ID 0).
|
||||
*
|
||||
* The core object is not visible to the permission manager's object manager
|
||||
* because it is implicit in the PipeWire connection and not sent through the
|
||||
* registry. This method allows setting explicit permissions on it, independent
|
||||
* of the default permissions.
|
||||
*
|
||||
* If not set (or set to PW_PERM_INVALID), the core inherits default_permissions.
|
||||
*
|
||||
* \ingroup wppermissionmanager
|
||||
* \param self the permission manager
|
||||
* \param permissions the permissions to apply to the core object
|
||||
*/
|
||||
void
|
||||
wp_permission_manager_set_core_permissions (WpPermissionManager *self,
|
||||
guint32 permissions)
|
||||
{
|
||||
g_return_if_fail (WP_IS_PERMISSION_MANAGER (self));
|
||||
|
||||
if (self->core_perms != permissions) {
|
||||
self->core_perms = permissions;
|
||||
update_permissions (self);
|
||||
}
|
||||
}
|
||||
|
||||
static guint32
|
||||
wp_permission_manager_add_match (WpPermissionManager *self,
|
||||
PermissionMatch *match)
|
||||
|
|
|
|||
|
|
@ -54,6 +54,10 @@ WP_API
|
|||
void wp_permission_manager_set_default_permissions (
|
||||
WpPermissionManager *self, guint32 permissions);
|
||||
|
||||
WP_API
|
||||
void wp_permission_manager_set_core_permissions (
|
||||
WpPermissionManager *self, guint32 permissions);
|
||||
|
||||
WP_API
|
||||
guint32 wp_permission_manager_add_interest_match (WpPermissionManager *self,
|
||||
WpPermissionMatchCallback callback, gpointer user_data,
|
||||
|
|
|
|||
|
|
@ -2657,8 +2657,28 @@ permission_manager_set_default_permissions (lua_State *L)
|
|||
}
|
||||
|
||||
wp_permission_manager_set_default_permissions (pm, perms);
|
||||
lua_pushboolean (L, TRUE);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
permission_manager_set_core_permissions (lua_State *L)
|
||||
{
|
||||
WpPermissionManager *pm = wplua_checkobject (L, 1,
|
||||
WP_TYPE_PERMISSION_MANAGER);
|
||||
guint32 perms = PW_PERM_ALL;
|
||||
|
||||
if (lua_isinteger (L, 2)) {
|
||||
perms = luaL_checkinteger (L, 2);
|
||||
} else if (lua_isstring (L, 2)) {
|
||||
const gchar *perms_str = luaL_checkstring (L, 2);
|
||||
if (!client_parse_permissions (perms_str, &perms))
|
||||
luaL_error (L, "invalid permission string: '%s'", perms_str);
|
||||
} else {
|
||||
luaL_error (L, "invalid permission argument");
|
||||
}
|
||||
|
||||
wp_permission_manager_set_core_permissions (pm, perms);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -2726,6 +2746,7 @@ permission_manager_update_permissions (lua_State *L)
|
|||
|
||||
static const luaL_Reg permission_manager_funcs[] = {
|
||||
{ "set_default_permissions", permission_manager_set_default_permissions },
|
||||
{ "set_core_permissions", permission_manager_set_core_permissions },
|
||||
{ "add_interest_match", permission_manager_add_interest_match },
|
||||
{ "add_interest_match_simple", permission_manager_add_interest_match_simple },
|
||||
{ "add_rules_match", permission_manager_add_rules_match },
|
||||
|
|
|
|||
|
|
@ -12,6 +12,12 @@ access.permission-managers = [
|
|||
# ## The default permissions to apply on all objects that dont have a match
|
||||
# default_permissions = "all"
|
||||
#
|
||||
# ## The permissions to apply specifically on the PipeWire core object
|
||||
# ## (ID 0). This is useful to allow clients to interact with the core
|
||||
# ## (e.g. enumerate objects) while restricting access to individual objects.
|
||||
# ## If not set, the default_permissions value is used for the core as well.
|
||||
# core_permissions = "rx"
|
||||
#
|
||||
# ## The rules to apply specific permissions to matched objects
|
||||
# rules = [
|
||||
# {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,11 @@ for _, pm_info in ipairs (config_pm_table) do
|
|||
config_pm:set_default_permissions (pm_info.default_permissions)
|
||||
end
|
||||
|
||||
-- Set core permissions if defined
|
||||
if pm_info.core_permissions ~= nil then
|
||||
config_pm:set_core_permissions (pm_info.core_permissions)
|
||||
end
|
||||
|
||||
-- Set rules match if defined
|
||||
if pm_info.rules ~= nil then
|
||||
config_pm:add_rules_match (Json.Raw (pm_info.rules))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue