core: add async create_client_node access check

This commit is contained in:
Wim Taymans 2017-04-13 10:38:54 +02:00
parent 4cf59e3953
commit a5b39019d1
3 changed files with 191 additions and 37 deletions

View file

@ -58,7 +58,7 @@ check_global_owner (PinosCore *core,
} }
static SpaResult static SpaResult
do_check_global (PinosAccess *access, do_view_global (PinosAccess *access,
PinosClient *client, PinosClient *client,
PinosGlobal *global) PinosGlobal *global)
{ {
@ -84,9 +84,65 @@ do_check_global (PinosAccess *access,
return SPA_RESULT_OK; return SPA_RESULT_OK;
} }
static SpaResult
do_create_node (PinosAccess *access,
PinosAccessData *data,
const char *factory_name,
const char *name,
PinosProperties *properties)
{
data->res = SPA_RESULT_OK;
data->complete_cb (data);
return SPA_RESULT_OK;
}
#if 0
static void
check_timeout (SpaSource *source,
void *d)
{
PinosAccessData *data = d;
data->res = SPA_RESULT_OK;
data->complete_cb (data);
}
#endif
static SpaResult
do_create_client_node (PinosAccess *access,
PinosAccessData *data,
const char *name,
PinosProperties *properties)
{
#if 0
struct timespec value;
SpaSource *timer;
pinos_log_debug ("access %p: check %s %p", access, name, properties);
timer = pinos_loop_add_timer (data->resource->core->main_loop->loop,
check_timeout,
data->async_copy (data, 0));
value.tv_sec = 3;
value.tv_nsec = 0;
pinos_loop_update_timer (data->resource->core->main_loop->loop,
timer,
&value,
NULL,
false);
return SPA_RESULT_RETURN_ASYNC (0);
#else
data->res = SPA_RESULT_OK;
return SPA_RESULT_OK;
#endif
}
static PinosAccess access_checks = static PinosAccess access_checks =
{ {
do_check_global, do_view_global,
do_create_node,
do_create_client_node,
}; };
static ModuleImpl * static ModuleImpl *

View file

@ -37,8 +37,10 @@ typedef struct _PinosAccessData PinosAccessData;
struct _PinosAccessData { struct _PinosAccessData {
SpaResult res; SpaResult res;
PinosResource *resource;
void *(*async_copy) (PinosAccessData *data, size_t size);
void (*complete_cb) (PinosAccessData *data); void (*complete_cb) (PinosAccessData *data);
void (*cancel_cb) (PinosAccessData *data); void (*free_cb) (PinosAccessData *data);
void *user_data; void *user_data;
}; };
@ -49,9 +51,18 @@ struct _PinosAccessData {
* Pinos Access support struct. * Pinos Access support struct.
*/ */
struct _PinosAccess { struct _PinosAccess {
SpaResult (*check_global) (PinosAccess *access, SpaResult (*view_global) (PinosAccess *access,
PinosClient *client, PinosClient *client,
PinosGlobal *global); PinosGlobal *global);
SpaResult (*create_node) (PinosAccess *access,
PinosAccessData *data,
const char *factory_name,
const char *name,
PinosProperties *properties);
SpaResult (*create_client_node) (PinosAccess *access,
PinosAccessData *data,
const char *name,
PinosProperties *properties);
}; };
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -38,8 +38,8 @@ typedef struct {
} PinosCoreImpl; } PinosCoreImpl;
#define ACCESS_CHECK_GLOBAL(client,global) (client->core->access && \ #define ACCESS_VIEW_GLOBAL(client,global) (client->core->access && \
client->core->access->check_global (client->core->access, \ client->core->access->view_global (client->core->access, \
client, global) == SPA_RESULT_OK) client, global) == SPA_RESULT_OK)
static void static void
@ -59,7 +59,7 @@ registry_bind (void *object,
if (&global->link == &core->global_list) if (&global->link == &core->global_list)
goto no_id; goto no_id;
if (!ACCESS_CHECK_GLOBAL (client, global)) if (!ACCESS_VIEW_GLOBAL (client, global))
goto no_id; goto no_id;
pinos_log_debug ("global %p: bind object id %d to %d", global, id, new_id); pinos_log_debug ("global %p: bind object id %d to %d", global, id, new_id);
@ -129,7 +129,7 @@ core_get_registry (void *object,
spa_list_insert (this->registry_resource_list.prev, &registry_resource->link); spa_list_insert (this->registry_resource_list.prev, &registry_resource->link);
spa_list_for_each (global, &this->global_list, link) { spa_list_for_each (global, &this->global_list, link) {
if (ACCESS_CHECK_GLOBAL (client, global)) if (ACCESS_VIEW_GLOBAL (client, global))
pinos_registry_notify_global (registry_resource, pinos_registry_notify_global (registry_resource,
global->id, global->id,
spa_type_map_get_type (this->type.map, global->type)); spa_type_map_get_type (this->type.map, global->type));
@ -161,32 +161,57 @@ core_create_node (void *object,
"not implemented"); "not implemented");
} }
static void typedef struct {
core_create_client_node (void *object, PinosAccessData data;
const char *name, char *name;
const SpaDict *props, PinosProperties *properties;
uint32_t new_id) uint32_t new_id;
bool async;
} AccessCreateClientNode;
static void *
async_create_client_node_copy (PinosAccessData *data, size_t size)
{ {
PinosResource *resource = object; AccessCreateClientNode *d;
d = calloc (1, sizeof (AccessCreateClientNode) + size);
memcpy (d, data, sizeof (AccessCreateClientNode));
d->name = strdup (d->name);
d->async = true;
d->data.user_data = SPA_MEMBER (d, sizeof (AccessCreateClientNode), void);
return d;
}
static void
async_create_client_node_free (PinosAccessData *data)
{
AccessCreateClientNode *d = (AccessCreateClientNode *) data;
if (d->async) {
if (d->data.free_cb)
d->data.free_cb (&d->data);
free (d->name);
free (d);
}
}
static void
async_create_client_node_complete (PinosAccessData *data)
{
AccessCreateClientNode *d = (AccessCreateClientNode *) data;
PinosResource *resource = d->data.resource;
PinosClient *client = resource->client; PinosClient *client = resource->client;
PinosClientNode *node; PinosClientNode *node;
SpaResult res; SpaResult res;
int data_fd, i; int data_fd;
PinosProperties *properties;
properties = pinos_properties_new (NULL, NULL); if (data->res != SPA_RESULT_OK)
if (properties == NULL) goto denied;
goto no_mem;
for (i = 0; i < props->n_items; i++) {
pinos_properties_set (properties, props->items[i].key,
props->items[i].value);
}
node = pinos_client_node_new (client, node = pinos_client_node_new (client,
new_id, d->new_id,
name, d->name,
properties); d->properties);
if (node == NULL) if (node == NULL)
goto no_mem; goto no_mem;
@ -200,6 +225,68 @@ core_create_client_node (void *object,
pinos_client_node_notify_done (node->resource, pinos_client_node_notify_done (node->resource,
data_fd); data_fd);
goto done;
no_mem:
pinos_log_error ("can't create client node");
pinos_core_notify_error (client->core_resource,
resource->id,
SPA_RESULT_NO_MEMORY,
"no memory");
goto done;
denied:
pinos_log_error ("create client node refused");
pinos_core_notify_error (client->core_resource,
resource->id,
SPA_RESULT_NO_PERMISSION,
"operation not allowed");
done:
async_create_client_node_free (&d->data);
return;
}
static void
core_create_client_node (void *object,
const char *name,
const SpaDict *props,
uint32_t new_id)
{
PinosResource *resource = object;
PinosClient *client = resource->client;
int i;
PinosProperties *properties;
AccessCreateClientNode access_data;
SpaResult res;
properties = pinos_properties_new (NULL, NULL);
if (properties == NULL)
goto no_mem;
for (i = 0; i < props->n_items; i++) {
pinos_properties_set (properties, props->items[i].key,
props->items[i].value);
}
access_data.data.resource = resource;
access_data.data.async_copy = async_create_client_node_copy;
access_data.data.complete_cb = async_create_client_node_complete;
access_data.data.free_cb = NULL;
access_data.name = (char *) name;
access_data.properties = properties;
access_data.new_id = new_id;
access_data.async = false;
if (client->core->access) {
access_data.data.res = SPA_RESULT_NO_PERMISSION;
res = client->core->access->create_client_node (client->core->access,
&access_data.data,
name,
properties);
} else {
res = access_data.data.res = SPA_RESULT_OK;
}
if (!SPA_RESULT_IS_ASYNC (res))
async_create_client_node_complete (&access_data.data);
return; return;
no_mem: no_mem:
@ -406,7 +493,7 @@ pinos_core_add_global (PinosCore *core,
pinos_log_debug ("global %p: new %u %s, owner %p", this, this->id, type_name, owner); pinos_log_debug ("global %p: new %u %s, owner %p", this, this->id, type_name, owner);
spa_list_for_each (registry, &core->registry_resource_list, link) spa_list_for_each (registry, &core->registry_resource_list, link)
if (ACCESS_CHECK_GLOBAL (registry->client, this)) if (ACCESS_VIEW_GLOBAL (registry->client, this))
pinos_registry_notify_global (registry, pinos_registry_notify_global (registry,
this->id, this->id,
type_name); type_name);
@ -445,7 +532,7 @@ pinos_global_destroy (PinosGlobal *global)
pinos_signal_emit (&global->destroy_signal, global); pinos_signal_emit (&global->destroy_signal, global);
spa_list_for_each (registry, &core->registry_resource_list, link) spa_list_for_each (registry, &core->registry_resource_list, link)
if (ACCESS_CHECK_GLOBAL (registry->client, global)) if (ACCESS_VIEW_GLOBAL (registry->client, global))
pinos_registry_notify_global_remove (registry, global->id); pinos_registry_notify_global_remove (registry, global->id);
pinos_map_remove (&core->objects, global->id); pinos_map_remove (&core->objects, global->id);