diff --git a/src/box/sysview_index.cc b/src/box/sysview_index.cc index b83054961c5dc7b9ec83d1e6657de46073aa2f95..9b1910128026e975c9c11a4cb025793f387f67e5 100644 --- a/src/box/sysview_index.cc +++ b/src/box/sysview_index.cc @@ -35,6 +35,7 @@ struct sysview_iterator { struct iterator base; struct iterator *source; + struct space *space; }; static inline struct sysview_iterator * @@ -63,7 +64,7 @@ sysview_iterator_next(struct iterator *iterator) class SysviewIndex *index = (class SysviewIndex *) iterator->index; struct tuple *tuple; while ((tuple = it->source->next(it->source)) != NULL) { - if (index->predicate(tuple)) + if (index->predicate(it->space, tuple)) return tuple; } return NULL; @@ -121,6 +122,7 @@ SysviewIndex::initIterator(struct iterator *iterator, pk->initIterator(it->source, type, key, part_count); iterator->index = (Index *) this; iterator->next = sysview_iterator_next; + it->space = source; } struct tuple * @@ -132,7 +134,7 @@ SysviewIndex::findByKey(const char *key, uint32_t part_count) const tnt_raise(ClientError, ER_MORE_THAN_ONE_TUPLE); primary_key_validate(pk->key_def, key, part_count); struct tuple *tuple = pk->findByKey(key, part_count); - if (tuple == NULL || !predicate(tuple)) + if (tuple == NULL || !predicate(source, tuple)) return NULL; return tuple; } @@ -148,11 +150,16 @@ SysviewIndex::replace(struct tuple *old_tuple, struct tuple *new_tuple, } static bool -vspace_predicate(struct tuple *tuple) +vspace_predicate(struct space *source, struct tuple *tuple) { + struct credentials *cr = current_user(); + if (PRIV_R & cr->universal_access) + return true; /* read access to unverse */ + if (PRIV_R & source->access[cr->auth_token].effective) + return true; /* read access to original space */ + uint32_t space_id = tuple_field_u32(tuple, 0); struct space *space = space_cache_find(space_id); - struct credentials *cr = current_user(); uint8_t effective = space->access[cr->auth_token].effective; return ((PRIV_R | PRIV_W) & (cr->universal_access | effective) || space->def.uid == cr->uid); @@ -169,11 +176,14 @@ SysviewVindexIndex::SysviewVindexIndex(struct key_def *key_def) } static bool -vuser_predicate(struct tuple *tuple) +vuser_predicate(struct space *source, struct tuple *tuple) { struct credentials *cr = current_user(); if (PRIV_R & cr->universal_access) - return true; + return true; /* read access to unverse */ + if (PRIV_R & source->access[cr->auth_token].effective) + return true; /* read access to original space */ + uint32_t uid = tuple_field_u32(tuple, 0); uint32_t owner_id = tuple_field_u32(tuple, 1); return uid == cr->uid || owner_id == cr->uid; @@ -185,11 +195,14 @@ SysviewVuserIndex::SysviewVuserIndex(struct key_def *key_def) } static bool -vpriv_predicate(struct tuple *tuple) +vpriv_predicate(struct space *source, struct tuple *tuple) { struct credentials *cr = current_user(); if (PRIV_R & cr->universal_access) - return true; + return true; /* read access to unverse */ + if (PRIV_R & source->access[cr->auth_token].effective) + return true; /* read access to original space */ + uint32_t grantor_id = tuple_field_u32(tuple, 0); uint32_t grantee_id = tuple_field_u32(tuple, 1); return grantor_id == cr->uid || grantee_id == cr->uid; @@ -201,18 +214,20 @@ SysviewVprivIndex::SysviewVprivIndex(struct key_def *key_def) } static bool -vfunc_predicate(struct tuple *tuple) +vfunc_predicate(struct space *source, struct tuple *tuple) { struct credentials *cr = current_user(); - if (PRIV_X & cr->universal_access) - return true; - uint32_t owner_id = tuple_field_u32(tuple, 1); - if (owner_id == cr->uid) - return true; + if ((PRIV_R | PRIV_X) & cr->universal_access) + return true; /* read or execute access to unverse */ + if (PRIV_R & source->access[cr->auth_token].effective) + return true; /* read access to original space */ + const char *name = tuple_field_cstr(tuple, 2); uint32_t name_len = strlen(name); struct func_def *func = func_by_name(name, name_len); - if (func != NULL && (PRIV_X & func->access[cr->auth_token].effective)) + assert(func != NULL); + uint8_t effective = func->access[cr->auth_token].effective; + if (func->uid == cr->uid || (PRIV_X & effective)) return true; return false; } diff --git a/src/box/sysview_index.h b/src/box/sysview_index.h index de3137a5b391030d65b91baab0f67ae438354ca9..fe1d93e9c7dedca5ba2b00ac5788c902dbd448e3 100644 --- a/src/box/sysview_index.h +++ b/src/box/sysview_index.h @@ -33,7 +33,7 @@ struct sysview_iterator; -typedef bool (*sysview_predicate_f)(struct tuple *); +typedef bool (*sysview_predicate_f)(struct space *source, struct tuple *); class SysviewIndex: public Index { public: diff --git a/test/box/access_sysview.result b/test/box/access_sysview.result index 501c2dfe310e951644352849256e59b287c73c28..69c72a935a7d2224eb33b5c75dbe7a96ea7f6add 100644 --- a/test/box/access_sysview.result +++ b/test/box/access_sysview.result @@ -238,10 +238,6 @@ box.schema.user.grant('guest', 'write', 'universe') box.session.su('guest') --- ... -#box.space._vspace:select{} ---- -- 13 -... #box.space._vindex:select{} --- - 32 @@ -270,6 +266,53 @@ box.space.test:drop() box.session.su('guest') --- ... +-- read access to original space also allow to read a view +box.session.su('admin') +--- +... +space_cnt = #box.space._space:select{} +--- +... +index_cnt = #box.space._index:select{} +--- +... +box.schema.user.grant('guest', 'read', 'space', '_space') +--- +... +box.schema.user.grant('guest', 'read', 'space', '_index') +--- +... +box.session.su('guest') +--- +... +#box.space._vspace:select{} == space_cnt +--- +- true +... +#box.space._vindex:select{} == index_cnt +--- +- true +... +box.session.su('admin') +--- +... +box.schema.user.revoke('guest', 'read', 'space', '_space') +--- +... +box.schema.user.revoke('guest', 'read', 'space', '_index') +--- +... +box.session.su('guest') +--- +... +#box.space._vspace:select{} < space_cnt +--- +- true +... +#box.space._vindex:select{} < index_cnt +--- +- true +... -- -- _vuser -- @@ -278,9 +321,35 @@ t = box.space._vuser:select(); return #t == 1 and t[1][3] == 'guest' --- - true ... -#box.space._vuser:select{} +-- read access to original space also allow to read a view +box.session.su('admin') +--- +... +user_cnt = #box.space._user:select{} +--- +... +box.schema.user.grant('guest', 'read', 'space', '_user') +--- +... +box.session.su('guest') +--- +... +#box.space._vuser:select{} == user_cnt +--- +- true +... +box.session.su('admin') +--- +... +box.schema.user.revoke('guest', 'read', 'space', '_user') --- -- 1 +... +box.session.su('guest') +--- +... +#box.space._vuser:select{} < user_cnt +--- +- true ... box.session.su('admin') --- @@ -324,9 +393,39 @@ box.space._vpriv.index[2]:select('role')[1][2] == session.uid() --- - true ... +-- read access to original space also allow to read a view +box.session.su('admin') +--- +... +box.schema.user.grant('guest', 'read', 'space', '_priv') +--- +... +priv_cnt = #box.space._priv:select{} +--- +... +box.session.su('guest') +--- +... +#box.space._vpriv:select{} == priv_cnt +--- +- true +... +box.session.su('admin') +--- +... +box.schema.user.revoke('guest', 'read', 'space', '_priv') +--- +... +box.session.su('guest') +--- +... cnt = #box.space._vpriv:select{} --- ... +cnt < priv_cnt +--- +- true +... box.session.su('admin') --- ... @@ -356,13 +455,43 @@ box.session.su('guest') -- -- _vfunc -- -cnt = #box.space._vfunc:select{} +box.session.su('admin') +--- +... +box.schema.func.create('test') +--- +... +-- read access to original space also allow to read a view +func_cnt = #box.space._func:select{} --- ... +box.schema.user.grant('guest', 'read', 'space', '_func') +--- +... +box.session.su('guest') +--- +... +#box.space._vfunc:select{} == func_cnt +--- +- true +... box.session.su('admin') --- ... -box.schema.func.create('test') +box.schema.user.revoke('guest', 'read', 'space', '_func') +--- +... +box.session.su('guest') +--- +... +cnt = #box.space._vfunc:select{} +--- +... +cnt < func_cnt +--- +- true +... +box.session.su('admin') --- ... box.schema.user.grant('guest', 'execute', 'function', 'test') diff --git a/test/box/access_sysview.test.lua b/test/box/access_sysview.test.lua index af8405c1b95feff1f4849de96b5e2fd23a043251..0fee93226d890a059f039763a692ddeff13e6de3 100644 --- a/test/box/access_sysview.test.lua +++ b/test/box/access_sysview.test.lua @@ -94,7 +94,6 @@ box.schema.user.revoke('guest', 'read', 'universe') box.schema.user.grant('guest', 'write', 'universe') box.session.su('guest') -#box.space._vspace:select{} #box.space._vindex:select{} #box.space._vuser:select{} #box.space._vpriv:select{} @@ -105,6 +104,22 @@ box.schema.user.revoke('guest', 'write', 'universe') box.space.test:drop() box.session.su('guest') +-- read access to original space also allow to read a view +box.session.su('admin') +space_cnt = #box.space._space:select{} +index_cnt = #box.space._index:select{} +box.schema.user.grant('guest', 'read', 'space', '_space') +box.schema.user.grant('guest', 'read', 'space', '_index') +box.session.su('guest') +#box.space._vspace:select{} == space_cnt +#box.space._vindex:select{} == index_cnt +box.session.su('admin') +box.schema.user.revoke('guest', 'read', 'space', '_space') +box.schema.user.revoke('guest', 'read', 'space', '_index') +box.session.su('guest') +#box.space._vspace:select{} < space_cnt +#box.space._vindex:select{} < index_cnt + -- -- _vuser -- @@ -112,7 +127,16 @@ box.session.su('guest') -- a guest user can read information about itself t = box.space._vuser:select(); return #t == 1 and t[1][3] == 'guest' -#box.space._vuser:select{} +-- read access to original space also allow to read a view +box.session.su('admin') +user_cnt = #box.space._user:select{} +box.schema.user.grant('guest', 'read', 'space', '_user') +box.session.su('guest') +#box.space._vuser:select{} == user_cnt +box.session.su('admin') +box.schema.user.revoke('guest', 'read', 'space', '_user') +box.session.su('guest') +#box.space._vuser:select{} < user_cnt box.session.su('admin') box.schema.user.grant('guest', 'read,write', 'universe') @@ -137,8 +161,19 @@ box.session.su('guest') -- a guest user can see granted 'public' role box.space._vpriv.index[2]:select('role')[1][2] == session.uid() +-- read access to original space also allow to read a view +box.session.su('admin') +box.schema.user.grant('guest', 'read', 'space', '_priv') +priv_cnt = #box.space._priv:select{} +box.session.su('guest') +#box.space._vpriv:select{} == priv_cnt +box.session.su('admin') +box.schema.user.revoke('guest', 'read', 'space', '_priv') +box.session.su('guest') cnt = #box.space._vpriv:select{} +cnt < priv_cnt + box.session.su('admin') box.schema.user.grant('guest', 'read,write', 'space', '_schema') box.session.su('guest') @@ -155,10 +190,22 @@ box.session.su('guest') -- _vfunc -- +box.session.su('admin') +box.schema.func.create('test') + +-- read access to original space also allow to read a view +func_cnt = #box.space._func:select{} +box.schema.user.grant('guest', 'read', 'space', '_func') +box.session.su('guest') +#box.space._vfunc:select{} == func_cnt +box.session.su('admin') +box.schema.user.revoke('guest', 'read', 'space', '_func') +box.session.su('guest') cnt = #box.space._vfunc:select{} +cnt < func_cnt + box.session.su('admin') -box.schema.func.create('test') box.schema.user.grant('guest', 'execute', 'function', 'test') box.session.su('guest')