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,9 +58,9 @@ check_global_owner (PinosCore *core,
}
static SpaResult
do_check_global (PinosAccess *access,
PinosClient *client,
PinosGlobal *global)
do_view_global (PinosAccess *access,
PinosClient *client,
PinosGlobal *global)
{
if (global->type == client->core->type.link) {
PinosLink *link = global->object;
@ -84,9 +84,65 @@ do_check_global (PinosAccess *access,
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 =
{
do_check_global,
do_view_global,
do_create_node,
do_create_client_node,
};
static ModuleImpl *

View file

@ -36,10 +36,12 @@ typedef struct _PinosAccessData PinosAccessData;
#include <pinos/server/resource.h>
struct _PinosAccessData {
SpaResult res;
void (*complete_cb) (PinosAccessData *data);
void (*cancel_cb) (PinosAccessData *data);
void *user_data;
SpaResult res;
PinosResource *resource;
void *(*async_copy) (PinosAccessData *data, size_t size);
void (*complete_cb) (PinosAccessData *data);
void (*free_cb) (PinosAccessData *data);
void *user_data;
};
@ -49,9 +51,18 @@ struct _PinosAccessData {
* Pinos Access support struct.
*/
struct _PinosAccess {
SpaResult (*check_global) (PinosAccess *access,
PinosClient *client,
PinosGlobal *global);
SpaResult (*view_global) (PinosAccess *access,
PinosClient *client,
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

View file

@ -38,9 +38,9 @@ typedef struct {
} PinosCoreImpl;
#define ACCESS_CHECK_GLOBAL(client,global) (client->core->access && \
client->core->access->check_global (client->core->access, \
client, global) == SPA_RESULT_OK)
#define ACCESS_VIEW_GLOBAL(client,global) (client->core->access && \
client->core->access->view_global (client->core->access, \
client, global) == SPA_RESULT_OK)
static void
registry_bind (void *object,
@ -59,7 +59,7 @@ registry_bind (void *object,
if (&global->link == &core->global_list)
goto no_id;
if (!ACCESS_CHECK_GLOBAL (client, global))
if (!ACCESS_VIEW_GLOBAL (client, global))
goto no_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_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,
global->id,
spa_type_map_get_type (this->type.map, global->type));
@ -161,32 +161,57 @@ core_create_node (void *object,
"not implemented");
}
static void
core_create_client_node (void *object,
const char *name,
const SpaDict *props,
uint32_t new_id)
typedef struct {
PinosAccessData data;
char *name;
PinosProperties *properties;
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;
PinosClientNode *node;
SpaResult res;
int data_fd, i;
PinosProperties *properties;
int data_fd;
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);
}
if (data->res != SPA_RESULT_OK)
goto denied;
node = pinos_client_node_new (client,
new_id,
name,
properties);
d->new_id,
d->name,
d->properties);
if (node == NULL)
goto no_mem;
@ -200,6 +225,68 @@ core_create_client_node (void *object,
pinos_client_node_notify_done (node->resource,
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;
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);
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,
this->id,
type_name);
@ -445,7 +532,7 @@ pinos_global_destroy (PinosGlobal *global)
pinos_signal_emit (&global->destroy_signal, global);
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_map_remove (&core->objects, global->id);