From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id 9FE3328399 for ; Tue, 31 Jul 2018 10:20:00 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id njrJ7bFEuYvs for ; Tue, 31 Jul 2018 10:20:00 -0400 (EDT) Received: from smtp16.mail.ru (smtp16.mail.ru [94.100.176.153]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id 9A36327664 for ; Tue, 31 Jul 2018 10:19:59 -0400 (EDT) From: Sergey Petrenko Content-Type: multipart/alternative; boundary="Apple-Mail=_44BC5B88-EA0C-429A-B8F1-110B1794E7D2" Mime-Version: 1.0 (Mac OS X Mail 11.5 \(3445.9.1\)) Subject: [tarantool-patches] [PATCH] Introduce separate entity object types for entity privileges. Message-Id: <56C246C1-B584-4D45-B120-5794757E3F54@tarantool.org> Date: Tue, 31 Jul 2018 17:19:55 +0300 Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-help: List-unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-subscribe: List-owner: List-post: List-archive: To: tarantool-patches@freelists.org, Konstantin Osipov --Apple-Mail=_44BC5B88-EA0C-429A-B8F1-110B1794E7D2 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii When granting or revoking a privilege on an entire entity, id 0 was used to indicate the fact that we don't grant a privilege on a single object, but on a whole entity. This caused confusion, because for entity USER, for example, id 0 is a valid object id (user 'guest' uses it). Any non-zero id dedicated to this cause obviously may be confused as = well. Fix this by creating separate schema_object_types for entities: SC_ENTITY_SPACE, SC_ENTITY_USER, etc. Also now granting privileges on an entity (e.g. space) may be done in 2 = ways: the old one: box.schema.user.grant('user', 'privilege', 'space') the new one: box.schema.user.grant('user', 'privilege', 'all spaces') The same applies to all entities. Closes: #3574 Prerequisite: #3524 --- = https://github.com/tarantool/tarantool/tree/sergepetrenko/gh-3574-whole-en= tity-types = https://github.com/tarantool/tarantool/issues/3574 = src/box/lua/schema.lua | 87 = ++++++++++++++++++++++++++++++++++++++------------ src/box/schema.cc | 16 ++++++---- src/box/schema.h | 23 +++++++------ src/box/schema_def.c | 22 ++++++++----- src/box/schema_def.h | 18 +++++++---- src/box/user.cc | 27 +++++++++------- test/box/access.result | 8 ++--- 7 files changed, 134 insertions(+), 67 deletions(-) diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua index b9b8c9004..eb984b1de 100644 --- a/src/box/lua/schema.lua +++ b/src/box/lua/schema.lua @@ -1731,14 +1731,21 @@ local priv_object_combo =3D { ["universe"] =3D box.priv.ALL, -- sic: we allow to grant 'execute' on space. This is a legacy -- bug, please fix it in 2.0 - ["space"] =3D bit.bxor(box.priv.ALL, box.priv.S, - box.priv.REVOKE, box.priv.GRANT), - ["sequence"] =3D bit.bor(box.priv.R, box.priv.W, box.priv.U, - box.priv.C, box.priv.A, box.priv.D), - ["function"] =3D bit.bor(box.priv.X, box.priv.U, - box.priv.C, box.priv.D), - ["role"] =3D bit.bor(box.priv.X, box.priv.U, - box.priv.C, box.priv.D), + ["space"] =3D bit.bxor(box.priv.ALL, box.priv.S, box.priv.C, + box.priv.REVOKE, box.priv.GRANT), + ["all spaces"] =3D bit.bxor(box.priv.ALL, box.priv.S, + box.priv.REVOKE, box.priv.GRANT), + ["sequence"] =3D bit.bor(box.priv.R, box.priv.W, box.priv.U, + box.priv.A, box.priv.D), + ["all sequences"] =3D bit.bor(box.priv.R, box.priv.W, + box.priv.C, box.priv.A, box.priv.D), + ["function"] =3D bit.bor(box.priv.X, box.priv.U, + box.priv.D), + ["all functions"] =3D bit.bor(box.priv.X, + box.priv.C, box.priv.D), + ["role"] =3D bit.bor(box.priv.X, box.priv.U, + box.priv.D), + ["all roles"] =3D bit.bor(box.priv.C, box.priv.D), } =20 -- @@ -1808,10 +1815,34 @@ local function object_resolve(object_type, = object_name) end return 0 end - if object_type =3D=3D 'space' then - if object_name =3D=3D nil or object_name =3D=3D 0 then - return 0 + if object_type =3D=3D 'all spaces' then + if object_name ~=3D nil and object_name ~=3D 0 then + box.error(box.error.ILLEGAL_PARAMS, "no object name allowed") + end + return 0 + end + if object_type =3D=3D 'all sequences' then + if object_name ~=3D nil and object_name ~=3D 0 then + box.error(box.error.ILLEGAL_PARAMS, "no object name allowed") end + return 0 + end + if object_type =3D=3D 'all functions' then + if object_name ~=3D nil and object_name ~=3D 0 then + box.error(box.error.ILLEGAL_PARAMS, "no object name allowed") + end + return 0 + end + if object_type =3D=3D 'all roles' then + if object_name ~=3D nil and object_name ~=3D 0 then + box.error(box.error.ILLEGAL_PARAMS, "no object name allowed") + end + return 0 + end + if object_type =3D=3D 'space' then + if object_name =3D=3D nil then + return nil + end local space =3D box.space[object_name] if space =3D=3D nil then box.error(box.error.NO_SUCH_SPACE, object_name) @@ -1819,9 +1850,9 @@ local function object_resolve(object_type, = object_name) return space.id end if object_type =3D=3D 'function' then - if object_name =3D=3D nil or object_name =3D=3D 0 then - return 0 - end + if object_name =3D=3D nil then + return nil + end local _vfunc =3D box.space[box.schema.VFUNC_ID] local func if type(object_name) =3D=3D 'string' then @@ -1836,16 +1867,19 @@ local function object_resolve(object_type, = object_name) end end if object_type =3D=3D 'sequence' then - if object_name =3D=3D nil or object_name =3D=3D 0 then - return 0 - end - local seq =3D sequence_resolve(object_name) + if object_name =3D=3D nil then + return nil + end + local seq =3D sequence_resolve(object_name) if seq =3D=3D nil then box.error(box.error.NO_SUCH_SEQUENCE, object_name) end return seq end if object_type =3D=3D 'role' then + if object_name =3D=3D nil then + return nil + end local _vuser =3D box.space[box.schema.VUSER_ID] local role if type(object_name) =3D=3D 'string' then @@ -1864,7 +1898,9 @@ local function object_resolve(object_type, = object_name) end =20 local function object_name(object_type, object_id) - if object_type =3D=3D 'universe' then + if object_type =3D=3D 'universe' or object_type =3D=3D 'all spaces' or + object_type =3D=3D 'all sequences' or object_type =3D=3D 'all = functions' or + object_type =3D=3D 'all roles' or object_type =3D=3D 'all users' then return "" end local space @@ -2079,9 +2115,14 @@ local function grant(uid, name, privilege, = object_type, object_name =3D privilege privilege =3D 'execute' end - local privilege_hex =3D privilege_check(privilege, object_type) =20 local oid =3D object_resolve(object_type, object_name) + -- allow for old syntax to grant privileges on an entity + if oid =3D=3D nil then + oid =3D 0 + object_type =3D 'all ' .. object_type .. 's' + end + local privilege_hex =3D privilege_check(privilege, object_type) options =3D options or {} if options.grantor =3D=3D nil then options.grantor =3D session.euid() @@ -2122,9 +2163,13 @@ local function revoke(uid, name, privilege, = object_type, object_name, options) object_name =3D privilege privilege =3D 'execute' end - local privilege_hex =3D privilege_check(privilege, object_type) options =3D options or {} local oid =3D object_resolve(object_type, object_name) + if oid =3D=3D nil then + oid =3D 0 + object_type =3D 'all ' .. object_type .. 's' + end + local privilege_hex =3D privilege_check(privilege, object_type) local _priv =3D box.space[box.schema.PRIV_ID] local _vpriv =3D box.space[box.schema.VPRIV_ID] local tuple =3D _vpriv:get{uid, object_type, oid} diff --git a/src/box/schema.cc b/src/box/schema.cc index 433f52c08..b81d2cd8a 100644 --- a/src/box/schema.cc +++ b/src/box/schema.cc @@ -536,10 +536,18 @@ schema_find_name(enum schema_object_type type, = uint32_t object_id) switch (type) { case SC_UNIVERSE: return ""; + case SC_ENTITY_SPACE: + return "SPACE"; + case SC_ENTITY_FUNCTION: + return "FUNCTION"; + case SC_ENTITY_SEQUENCE: + return "SEQUENCE"; + case SC_ENTITY_ROLE: + return "ROLE"; + case SC_ENTITY_USER: + return "USER"; case SC_SPACE: { - if (object_id =3D=3D 0) - return "SPACE"; struct space *space =3D space_by_id(object_id); if (space =3D=3D NULL) break; @@ -547,8 +555,6 @@ schema_find_name(enum schema_object_type type, = uint32_t object_id) } case SC_FUNCTION: { - if (object_id =3D=3D 0) - return "FUNCTION"; struct func *func =3D func_by_id(object_id); if (func =3D=3D NULL) break; @@ -556,8 +562,6 @@ schema_find_name(enum schema_object_type type, = uint32_t object_id) } case SC_SEQUENCE: { - if (object_id =3D=3D 0) - return "SEQUENCE"; struct sequence *seq =3D sequence_by_id(object_id); if (seq =3D=3D NULL) break; diff --git a/src/box/schema.h b/src/box/schema.h index 0822262d0..f1735ff34 100644 --- a/src/box/schema.h +++ b/src/box/schema.h @@ -250,16 +250,19 @@ static inline struct access * entity_access_get(enum schema_object_type type) { - switch (type) { - case SC_SPACE: - return entity_access.space; - case SC_FUNCTION: - return entity_access.function; - case SC_SEQUENCE: - return entity_access.sequence; - default: - return NULL; - } + switch (type) { + case SC_SPACE: + case SC_ENTITY_SPACE: + return entity_access.space; + case SC_FUNCTION: + case SC_ENTITY_FUNCTION: + return entity_access.function; + case SC_SEQUENCE: + case SC_ENTITY_SEQUENCE: + return entity_access.sequence; + default: + return NULL; + } } =20 #endif /* INCLUDES_TARANTOOL_BOX_SCHEMA_H */ diff --git a/src/box/schema_def.c b/src/box/schema_def.c index 97c074ab2..caec2e00d 100644 --- a/src/box/schema_def.c +++ b/src/box/schema_def.c @@ -31,14 +31,20 @@ #include "schema_def.h" =20 static const char *object_type_strs[] =3D { - /* [SC_UKNNOWN] =3D */ "unknown", - /* [SC_UNIVERSE] =3D */ "universe", - /* [SC_SPACE] =3D */ "space", - /* [SC_FUNCTION] =3D */ "function", - /* [SC_USER] =3D */ "user", - /* [SC_ROLE] =3D */ "role", - /* [SC_SEQUENCE] =3D */ "sequence", - /* [SC_COLLATION] =3D */ "collation", + /* [SC_UKNNOWN] =3D */ "unknown", + /* [SC_UNIVERSE] =3D */ "universe", + /* [SC_SPACE] =3D */ "space", + /* [SC_ENTITY_SPACE] =3D */ "all spaces", + /* [SC_FUNCTION] =3D */ "function", + /* [SC_ENTITY_FUNCTION] =3D */ "all functions", + /* [SC_USER] =3D */ "user", + /* [SC_ENTITY_USER] =3D */ "all users", + /* [SC_ROLE] =3D */ "role", + /* [SC_ENTITY_ROLE] =3D */ "all roles", + /* [SC_SEQUENCE] =3D */ "sequence", + /* [SC_ENTITY_SEQUENCE] =3D */ "all sequences", + /* [SC_COLLATION] =3D */ "collation", + /* [SC_ENTITY_COLLATION] =3D */ "all collations", }; =20 enum schema_object_type diff --git a/src/box/schema_def.h b/src/box/schema_def.h index 2edb8d37f..0c917094c 100644 --- a/src/box/schema_def.h +++ b/src/box/schema_def.h @@ -223,12 +223,18 @@ enum schema_object_type { SC_UNKNOWN =3D 0, SC_UNIVERSE =3D 1, SC_SPACE =3D 2, - SC_FUNCTION =3D 3, - SC_USER =3D 4, - SC_ROLE =3D 5, - SC_SEQUENCE =3D 6, - SC_COLLATION =3D 7, - schema_object_type_MAX =3D 8 + SC_ENTITY_SPACE =3D 3, + SC_FUNCTION =3D 4, + SC_ENTITY_FUNCTION =3D 5, + SC_USER =3D 6, + SC_ENTITY_USER =3D 7, + SC_ROLE =3D 8, + SC_ENTITY_ROLE =3D 9, + SC_SEQUENCE =3D 10, + SC_ENTITY_SEQUENCE =3D 11, + SC_COLLATION =3D 12, + SC_ENTITY_COLLATION =3D 13, + schema_object_type_MAX =3D 13 }; =20 enum schema_object_type diff --git a/src/box/user.cc b/src/box/user.cc index fbf06566a..eec785652 100644 --- a/src/box/user.cc +++ b/src/box/user.cc @@ -207,12 +207,23 @@ access_find(struct priv_def *priv) access =3D universe.access; break; } + case SC_ENTITY_SPACE: + { + access =3D entity_access.space; + break; + } + case SC_ENTITY_FUNCTION: + { + access =3D entity_access.function; + break; + } + case SC_ENTITY_SEQUENCE: + { + access =3D entity_access.sequence; + break; + } case SC_SPACE: { - if (priv->object_id =3D=3D 0) { - access =3D entity_access.space; - break; - } struct space *space =3D space_by_id(priv->object_id); if (space) access =3D space->access; @@ -220,10 +231,6 @@ access_find(struct priv_def *priv) } case SC_FUNCTION: { - if (priv->object_id =3D=3D 0) { - access =3D entity_access.function; - break; - } struct func *func =3D func_by_id(priv->object_id); if (func) access =3D func->access; @@ -231,10 +238,6 @@ access_find(struct priv_def *priv) } case SC_SEQUENCE: { - if (priv->object_id =3D=3D 0) { - access =3D entity_access.sequence; - break; - } struct sequence *seq =3D sequence_by_id(priv->object_id); if (seq) access =3D seq->access; diff --git a/test/box/access.result b/test/box/access.result index f4669a4a3..30fcb6455 100644 --- a/test/box/access.result +++ b/test/box/access.result @@ -1733,19 +1733,19 @@ box.session.su('admin') -- prerequisite gh-945 box.schema.user.grant("guest", "alter", "function") --- -- error: Unsupported function privilege 'alter' +- error: Unsupported all functions privilege 'alter' ... box.schema.user.grant("guest", "execute", "sequence") --- -- error: Unsupported sequence privilege 'execute' +- error: Unsupported all sequences privilege 'execute' ... box.schema.user.grant("guest", "read,execute", "sequence") --- -- error: Unsupported sequence privilege 'read,execute' +- error: Unsupported all sequences privilege 'read,execute' ... box.schema.user.grant("guest", "read,write,execute", "role") --- -- error: Unsupported role privilege 'read,write,execute' +- error: Unsupported all roles privilege 'read,write,execute' ... -- Check entities DML box.schema.user.create("tester", { password =3D '123' }) --=20 2.15.2 (Apple Git-101.1)= --Apple-Mail=_44BC5B88-EA0C-429A-B8F1-110B1794E7D2 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=us-ascii

When = granting or revoking a privilege on an entire entity, id 0 was = used
to indicate the fact = that we don't grant a privilege on a single object,
but on a whole entity. This caused = confusion, because for entity USER,
for example, id 0 is a valid object id (user 'guest' = uses it).
Any = non-zero id dedicated to this cause obviously may be confused as = well.
Fix this by creating = separate schema_object_types for entities:
SC_ENTITY_SPACE, SC_ENTITY_USER, etc.
Also now granting privileges on an = entity (e.g. space) may be done in 2 ways:
the old one: box.schema.user.grant('user', = 'privilege', 'space')
the = new one: box.schema.user.grant('user', 'privilege', 'all = spaces')
The = same applies to all entities.

Closes: #3574
Prerequisite: #3524
---
https://github.com/tarantool/tarantool/tree/sergepetrenko/gh-35= 74-whole-entity-types
https://github.com/tarantool/tarantool/issues/3574

 src/box/lua/schema.lua | 87 = ++++++++++++++++++++++++++++++++++++++------------
 src/box/schema.cc | 16 ++++++----
 src/box/schema.h | 23 +++++++------
 src/box/schema_def.c | 22 = ++++++++-----
 src/box/schema_def.h | 18 +++++++----
 src/box/user.cc | 27 +++++++++-------
 test/box/access.result | 8 = ++---
 7 files changed, = 134 insertions(+), 67 deletions(-)

diff --git = a/src/box/lua/schema.lua b/src/box/lua/schema.lua
index b9b8c9004..eb984b1de = 100644
--- = a/src/box/lua/schema.lua
+++ = b/src/box/lua/schema.lua
@@ = -1731,14 +1731,21 @@ local priv_object_combo =3D {
     ["universe"]= =3D box.priv.ALL,
 -- sic: we allow to grant 'execute' on space. This is a = legacy
 -- bug, please fix it in 2.0
- ["space"] =3D bit.bxor(box.priv.ALL, = box.priv.S,
- = box.priv.REVOKE, box.priv.GRANT),
- ["sequence"] =3D bit.bor(box.priv.R, box.priv.W, = box.priv.U,
- = box.priv.C, box.priv.A, box.priv.D),
- ["function"] =3D bit.bor(box.priv.X, = box.priv.U,
- = box.priv.C, box.priv.D),
- = ["role"] =3D bit.bor(box.priv.X, box.priv.U,
- box.priv.C, box.priv.D),
+ ["space"] =3D bit.bxor(box.priv.ALL, = box.priv.S, box.priv.C,
+ = box.priv.REVOKE, box.priv.GRANT),
+ ["all spaces"] =3D bit.bxor(box.priv.ALL, = box.priv.S,
+ = box.priv.REVOKE, box.priv.GRANT),
+ ["sequence"] =3D bit.bor(box.priv.R, box.priv.W, = box.priv.U,
+ = box.priv.A, box.priv.D),
+ = ["all sequences"] =3D bit.bor(box.priv.R, box.priv.W,
+ box.priv.C, box.priv.A, = box.priv.D),
+ = ["function"] =3D bit.bor(box.priv.X, box.priv.U,
+ box.priv.D),
+ ["all functions"] =3D = bit.bor(box.priv.X,
+ = box.priv.C, box.priv.D),
+ = ["role"] =3D bit.bor(box.priv.X, box.priv.U,
+ box.priv.D),
+ ["all roles"] =3D bit.bor(box.priv.C, = box.priv.D),
 }
 
 --
@@ = -1808,10 +1815,34 @@ local function object_resolve(object_type, = object_name)
         end
         return = 0
     end
- if object_type =3D=3D 'space' = then
- if object_name =3D=3D = nil or object_name =3D=3D 0 then
- return 0
+ if = object_type =3D=3D 'all spaces' then
+ if object_name ~=3D nil and object_name ~=3D 0 = then
+ = box.error(box.error.ILLEGAL_PARAMS, "no object name allowed")
+ end
+ return 0
+ = end
+ if object_type =3D=3D = 'all sequences' then
+ if = object_name ~=3D nil and object_name ~=3D 0 then
+ box.error(box.error.ILLEGAL_PARAMS, = "no object name allowed")
         end
+ return 0
+ end
+ if object_type =3D=3D 'all functions' then
+ if object_name ~=3D nil and = object_name ~=3D 0 then
+ = box.error(box.error.ILLEGAL_PARAMS, "no object name allowed")
+ end
+ return 0
+ = end
+ if object_type =3D=3D = 'all roles' then
+ if = object_name ~=3D nil and object_name ~=3D 0 then
+ box.error(box.error.ILLEGAL_PARAMS, = "no object name allowed")
+ = end
+ return 0
+ end
+ if object_type =3D=3D 'space' then
+ if object_name =3D=3D nil = then
+ return = nil
+ end
         local = space =3D box.space[object_name]
         if= space =3D=3D nil then
          &nb= sp;  box.error(box.error.NO_SUCH_SPACE, object_name)
@@ -1819,9 +1850,9 @@ local function = object_resolve(object_type, object_name)
         return = space.id
     end
     if = object_type =3D=3D 'function' then
- if object_name =3D=3D nil or object_name =3D=3D 0 = then
- return 0
- end
+ if object_name =3D=3D nil then
+ return nil
+ end
         local = _vfunc =3D box.space[box.schema.VFUNC_ID]
         local = func
         if = type(object_name) =3D=3D 'string' then
@@ -1836,16 +1867,19 @@ local function = object_resolve(object_type, object_name)
         end
     end
     if = object_type =3D=3D 'sequence' then
- if object_name =3D=3D nil or object_name =3D=3D 0 = then
- return 0
- end
- local seq =3D = sequence_resolve(object_name)
+ if = object_name =3D=3D nil then
+ = return nil
+ = end
+ local seq =3D = sequence_resolve(object_name)
         if seq = =3D=3D nil then
          &nb= sp;  box.error(box.error.NO_SUCH_SEQUENCE, = object_name)
         end
         return = seq
     end
     if = object_type =3D=3D 'role' then
+ if object_name =3D=3D nil then
+ return nil
+ end
         local = _vuser =3D box.space[box.schema.VUSER_ID]
         local = role
         if = type(object_name) =3D=3D 'string' then
@@ -1864,7 +1898,9 @@ local function = object_resolve(object_type, object_name)
 end
 
 local function object_name(object_type, = object_id)
- if = object_type =3D=3D 'universe' then
+ if object_type =3D=3D 'universe' or object_type =3D=3D= 'all spaces' or
+ = object_type =3D=3D 'all sequences' or object_type =3D=3D 'all functions' = or
+ object_type =3D=3D = 'all roles' or object_type =3D=3D 'all users' then
         return = ""
     end
     local = space
@@ -2079,9 +2115,14 @@ = local function grant(uid, name, privilege, object_type,
         object_na= me =3D privilege
         privilege= =3D 'execute'
     end
- local privilege_hex =3D = privilege_check(privilege, object_type)
 
     local oid =3D = object_resolve(object_type, object_name)
+ -- allow for old syntax to grant privileges on an = entity
+ if = oid =3D=3D nil then
+ = oid =3D 0
+ = object_type =3D 'all ' .. object_type .. 's'
+ end
+ local privilege_hex =3D privilege_check(privilege, = object_type)
     options =3D options or = {}
     if options.grantor =3D=3D nil = then
         options.g= rantor =3D session.euid()
@@ = -2122,9 +2163,13 @@ local function revoke(uid, name, privilege, = object_type, object_name, options)
         object_na= me =3D privilege
         privilege= =3D 'execute'
     end
- local privilege_hex =3D = privilege_check(privilege, object_type)
     options =3D options or = {}
     local oid =3D = object_resolve(object_type, object_name)
+ if oid =3D=3D nil then
+ oid =3D 0
+ object_type =3D 'all ' .. object_type .. = 's'
+ end
+ local privilege_hex =3D = privilege_check(privilege, object_type)
     local _priv =3D = box.space[box.schema.PRIV_ID]
     local _vpriv =3D = box.space[box.schema.VPRIV_ID]
     local tuple =3D = _vpriv:get{uid, object_type, oid}
diff --git a/src/box/schema.cc b/src/box/schema.cc
index = 433f52c08..b81d2cd8a 100644
--- = a/src/box/schema.cc
+++ b/src/box/schema.cc
@@ = -536,10 +536,18 @@ schema_find_name(enum schema_object_type type, = uint32_t object_id)
  = switch (type) {
  = case SC_UNIVERSE:
  = return "";
+ = case SC_ENTITY_SPACE:
+ = return "SPACE";
+ = case SC_ENTITY_FUNCTION:
+ = return "FUNCTION";
+ = case SC_ENTITY_SEQUENCE:
+ = return "SEQUENCE";
+ = case SC_ENTITY_ROLE:
+ = return "ROLE";
+ = case SC_ENTITY_USER:
+ = return "USER";
  = case SC_SPACE:
  = {
- if (object_id =3D=3D= 0)
- return = "SPACE";
  = struct space *space =3D space_by_id(object_id);
  if (space =3D=3D NULL)
  break;
@@ -547,8 +555,6 @@ = schema_find_name(enum schema_object_type type, uint32_t = object_id)
  = }
  case = SC_FUNCTION:
  = {
- if (object_id =3D=3D= 0)
- return = "FUNCTION";
  = struct func *func =3D func_by_id(object_id);
  if (func =3D=3D NULL)
  break;
@@ -556,8 +562,6 @@ = schema_find_name(enum schema_object_type type, uint32_t = object_id)
  = }
  case = SC_SEQUENCE:
  = {
- if (object_id =3D=3D= 0)
- return = "SEQUENCE";
  = struct sequence *seq =3D sequence_by_id(object_id);
  if (seq =3D=3D NULL)
  break;
diff --git a/src/box/schema.h = b/src/box/schema.h
index = 0822262d0..f1735ff34 100644
--- = a/src/box/schema.h
+++ = b/src/box/schema.h
@@ = -250,16 +250,19 @@ static inline
 struct access *
 entity_access_get(enum schema_object_type = type)
 {
- switch (type) {
- case SC_SPACE:
- return entity_access.space;
- case SC_FUNCTION:
- return = entity_access.function;
- = case SC_SEQUENCE:
- = return entity_access.sequence;
- default:
- = return NULL;
- = }
+ switch (type) = {
+ case = SC_SPACE:
+ = case SC_ENTITY_SPACE:
+ = return entity_access.space;
+ = case SC_FUNCTION:
+ = case SC_ENTITY_FUNCTION:
+ = return entity_access.function;
+ case SC_SEQUENCE:
+ case SC_ENTITY_SEQUENCE:
+ return = entity_access.sequence;
+ = default:
+ = return NULL;
+ = }
 }
 
 #endif /* INCLUDES_TARANTOOL_BOX_SCHEMA_H = */
diff --git = a/src/box/schema_def.c b/src/box/schema_def.c
index 97c074ab2..caec2e00d = 100644
--- = a/src/box/schema_def.c
+++ = b/src/box/schema_def.c
@@ = -31,14 +31,20 @@
 #include "schema_def.h"
 
 static const char *object_type_strs[] =3D {
- /* [SC_UKNNOWN] =3D */ = "unknown",
- = /* [SC_UNIVERSE] =3D */ "universe",
- /* [SC_SPACE] =3D */ "space",
- /* [SC_FUNCTION] =3D */ = "function",
- = /* [SC_USER] =3D */ "user",
- = /* [SC_ROLE] =3D */ "role",
- = /* [SC_SEQUENCE] =3D */ "sequence",
- /* [SC_COLLATION] =3D */ "collation",
+ /* [SC_UKNNOWN] =3D */ = "unknown",
+ = /* [SC_UNIVERSE] =3D */ "universe",
+ /* [SC_SPACE] =3D */ "space",
+ /* [SC_ENTITY_SPACE] =3D */ = "all spaces",
+ = /* [SC_FUNCTION] =3D */ "function",
+ /* [SC_ENTITY_FUNCTION] =3D */ "all = functions",
+ = /* [SC_USER] =3D */ "user",
+ /* [SC_ENTITY_USER] =3D */ "all = users",
+ = /* [SC_ROLE] =3D */ "role",
+ /* [SC_ENTITY_ROLE] =3D */ "all = roles",
+ = /* [SC_SEQUENCE] =3D */ "sequence",
+ /* [SC_ENTITY_SEQUENCE] =3D */ "all = sequences",
+ = /* [SC_COLLATION] =3D */ "collation",
+ /* [SC_ENTITY_COLLATION] =3D */ = "all collations",
 };
 
 enum schema_object_type
diff --git a/src/box/schema_def.h = b/src/box/schema_def.h
index = 2edb8d37f..0c917094c 100644
--- = a/src/box/schema_def.h
+++ = b/src/box/schema_def.h
@@ = -223,12 +223,18 @@ enum schema_object_type {
  SC_UNKNOWN =3D 0,
  SC_UNIVERSE =3D 1,
  SC_SPACE =3D 2,
- SC_FUNCTION =3D 3,
- SC_USER =3D 4,
- SC_ROLE =3D 5,
- SC_SEQUENCE =3D 6,
- SC_COLLATION =3D 7,
- schema_object_type_MAX =3D = 8
+ SC_ENTITY_SPACE = =3D 3,
+ = SC_FUNCTION =3D 4,
+ = SC_ENTITY_FUNCTION =3D 5,
+ = SC_USER =3D 6,
+ = SC_ENTITY_USER =3D 7,
+ = SC_ROLE =3D 8,
+ = SC_ENTITY_ROLE =3D 9,
+ = SC_SEQUENCE =3D 10,
+ = SC_ENTITY_SEQUENCE =3D 11,
+ = SC_COLLATION =3D 12,
+ = SC_ENTITY_COLLATION =3D 13,
+ = schema_object_type_MAX =3D 13
 };
 
 enum schema_object_type
diff --git a/src/box/user.cc b/src/box/user.cc
index = fbf06566a..eec785652 100644
--- = a/src/box/user.cc
+++ b/src/box/user.cc
@@ = -207,12 +207,23 @@ access_find(struct priv_def *priv)
  access =3D = universe.access;
  = break;
  = }
+ case = SC_ENTITY_SPACE:
+ = {
+ access =3D = entity_access.space;
+ = break;
+ = }
+ case = SC_ENTITY_FUNCTION:
+ = {
+ access =3D = entity_access.function;
+ = break;
+ = }
+ case = SC_ENTITY_SEQUENCE:
+ = {
+ access =3D = entity_access.sequence;
+ = break;
+ = }
  case = SC_SPACE:
  = {
- if = (priv->object_id =3D=3D 0) {
- access =3D entity_access.space;
- break;
- }
  struct space *space =3D = space_by_id(priv->object_id);
  if (space)
  access =3D space->access;
@@ -220,10 +231,6 @@ access_find(struct = priv_def *priv)
  = }
  case = SC_FUNCTION:
  = {
- if = (priv->object_id =3D=3D 0) {
- access =3D entity_access.function;
- break;
- }
  struct func *func =3D = func_by_id(priv->object_id);
  if (func)
  access =3D func->access;
@@ -231,10 +238,6 @@ access_find(struct = priv_def *priv)
  = }
  case = SC_SEQUENCE:
  = {
- if = (priv->object_id =3D=3D 0) {
- access =3D entity_access.sequence;
- break;
- }
  struct sequence *seq =3D = sequence_by_id(priv->object_id);
  if (seq)
  access =3D seq->access;
diff --git a/test/box/access.result = b/test/box/access.result
index = f4669a4a3..30fcb6455 100644
--- = a/test/box/access.result
+++ = b/test/box/access.result
@@ = -1733,19 +1733,19 @@ box.session.su('admin')
 -- prerequisite gh-945
 box.schema.user.grant("guest", = "alter", "function")
 ---
-- = error: Unsupported function privilege 'alter'
+- error: Unsupported all functions = privilege 'alter'
 ...
 box.schema.user.grant("guest", "execute", = "sequence")
 ---
-- = error: Unsupported sequence privilege 'execute'
+- error: Unsupported all sequences = privilege 'execute'
 ...
 box.schema.user.grant("guest", "read,execute", = "sequence")
 ---
-- = error: Unsupported sequence privilege 'read,execute'
+- error: Unsupported all sequences = privilege 'read,execute'
 ...
 box.schema.user.grant("guest", "read,write,execute", = "role")
 ---
-- = error: Unsupported role privilege 'read,write,execute'
+- error: Unsupported all roles = privilege 'read,write,execute'
 ...
 -- Check entities DML
 box.schema.user.create("tester", { password =3D = '123' })
-- 
2.15.2 = (Apple Git-101.1)
= --Apple-Mail=_44BC5B88-EA0C-429A-B8F1-110B1794E7D2--