protocol-native: add security context API

Add a new extension that can create a server on a user provided socket
with user provided security properties.

This is mainly used in flatpaks that want to create and bind a pipewire
socket with specific permissions for the flatpak app.

The flatpak will also provide an fd that will be closed when the server
can be removed.
This commit is contained in:
Wim Taymans 2024-02-08 10:04:21 +01:00
parent c5e8da7247
commit e7846fc12a
8 changed files with 580 additions and 1 deletions

View file

@ -0,0 +1,111 @@
/* PipeWire */
/* SPDX-FileCopyrightText: Copyright © 2019 Wim Taymans */
/* SPDX-License-Identifier: MIT */
#ifndef PIPEWIRE_EXT_SECURITY_CONTEXT_H
#define PIPEWIRE_EXT_SECURITY_CONTEXT_H
#ifdef __cplusplus
extern "C" {
#endif
#include <spa/utils/defs.h>
/** \defgroup pw_security_context Security Context
* Security Context interface
*/
/**
* \addtogroup pw_security_context
* \{
*/
#define PW_TYPE_INTERFACE_SecurityContext PW_TYPE_INFO_INTERFACE_BASE "SecurityContext"
#define PW_SECURITY_CONTEXT_PERM_MASK PW_PERM_RWX
#define PW_VERSION_SECURITY_CONTEXT 3
struct pw_security_context;
#define PW_EXTENSION_MODULE_SECURITY_CONTEXT PIPEWIRE_MODULE_PREFIX "module-security-context"
#define PW_SECURITY_CONTEXT_EVENT_NUM 0
/** \ref pw_security_context events */
struct pw_security_context_events {
#define PW_VERSION_SECURITY_CONTEXT_EVENTS 0
uint32_t version;
};
#define PW_SECURITY_CONTEXT_METHOD_ADD_LISTENER 0
#define PW_SECURITY_CONTEXT_METHOD_CREATE 1
#define PW_SECURITY_CONTEXT_METHOD_NUM 2
/** \ref pw_security_context methods */
struct pw_security_context_methods {
#define PW_VERSION_SECURITY_CONTEXT_METHODS 0
uint32_t version;
int (*add_listener) (void *object,
struct spa_hook *listener,
const struct pw_security_context_events *events,
void *data);
/**
* Create a new security context
*
* Creates a new security context with a socket listening FD.
* PipeWire will accept new client connections on listen_fd.
*
* listen_fd must be ready to accept new connections when this request is
* sent by the client. In other words, the client must call bind(2) and
* listen(2) before sending the FD.
*
* close_fd is a FD closed by the client when PipeWire should stop
* accepting new connections on listen_fd.
*
* PipeWire must continue to accept connections on listen_fd when
* the client which created the security context disconnects.
*
* After sending this request, closing listen_fd and close_fd remains the
* only valid operation on them.
*
* \param engine_name a unique sandbox engine name.
* \param listen_fd the fd to listen on for new connections
* \param close_fd the fd used to stop listening
* \param props extra (engine_name specific) properties.
*
* See https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/main/staging/security-context/engines.md
* For a list of engine_names and the properties to set.
*
* This requires X and W permissions on the security_context.
*/
int (*create) (void *object,
const char *engine_name,
int listen_fd,
int close_fd,
const struct spa_dict *props);
};
#define pw_security_context_method(o,method,version,...) \
({ \
int _res = -ENOTSUP; \
spa_interface_call_res((struct spa_interface*)o, \
struct pw_security_context_methods, _res, \
method, version, ##__VA_ARGS__); \
_res; \
})
#define pw_security_context_add_listener(c,...) pw_security_context_method(c,add_listener,0,__VA_ARGS__)
#define pw_security_context_create(c,...) pw_security_context_method(c,create,0,__VA_ARGS__)
/**
* \}
*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* PIPEWIRE_EXT_SECURITY_CONTEXT_H */

View file

@ -81,7 +81,7 @@ struct pw_protocol_marshal {
};
struct pw_protocol_implementation {
#define PW_VERSION_PROTOCOL_IMPLEMENTATION 0
#define PW_VERSION_PROTOCOL_IMPLEMENTATION 1
uint32_t version;
struct pw_protocol_client * (*new_client) (struct pw_protocol *protocol,
@ -90,6 +90,10 @@ struct pw_protocol_implementation {
struct pw_protocol_server * (*add_server) (struct pw_protocol *protocol,
struct pw_impl_core *core,
const struct spa_dict *props);
struct pw_protocol_server * (*add_fd_server) (struct pw_protocol *protocol,
struct pw_impl_core *core,
int listen_fd, int close_fd,
const struct spa_dict *props);
};
struct pw_protocol_events {
@ -101,6 +105,7 @@ struct pw_protocol_events {
#define pw_protocol_new_client(p,...) (pw_protocol_get_implementation(p)->new_client(p,__VA_ARGS__))
#define pw_protocol_add_server(p,...) (pw_protocol_get_implementation(p)->add_server(p,__VA_ARGS__))
#define pw_protocol_add_fd_server(p,...) (pw_protocol_get_implementation(p)->add_fd_server(p,__VA_ARGS__))
#define pw_protocol_ext(p,type,method,...) (((type*)pw_protocol_get_extension(p))->method( __VA_ARGS__))
struct pw_protocol *pw_protocol_new(struct pw_context *context, const char *name, size_t user_data_size);