From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Kirill Yukhin Subject: [PATCH v2 4/4] sql: check read access while executing SQL query Date: Thu, 25 Oct 2018 11:17:12 +0300 Message-Id: <4190713e5ce5192e75456defc9d0a904ce422aff.1540388902.git.kyukhin@tarantool.org> In-Reply-To: References: In-Reply-To: References: To: vdavydov.dev@gmail.com Cc: tarantool-patches@freelists.org, Kirill Yukhin List-ID: Since SQL front-end is not using box API, no checkes for read access are performed by VDBE engine. Add check to IteratorOpen op-code to make sure that read privilege exists for given space. Note, that there's is no need to perform DML/DDL checkes as they're performed by Tarantool's core. @TarantoolBot document Title: Document behaviour of SQL in presence of read access restrictions. Need to clarify, that if there's no read access to the space, then not only SELECT statements will fail, but also those DML which implies reading from spaces indirectly, e.g.: UPDATE t1 SET a=2 WHERE b=3; Closes #2362 --- src/box/sql/vdbe.c | 5 ++ test/sql/gh-2362-select-access-rights.result | 110 +++++++++++++++++++++++++ test/sql/gh-2362-select-access-rights.test.lua | 42 ++++++++++ 3 files changed, 157 insertions(+) create mode 100644 test/sql/gh-2362-select-access-rights.result create mode 100644 test/sql/gh-2362-select-access-rights.test.lua diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c index 7c1015c..10b58b4 100644 --- a/src/box/sql/vdbe.c +++ b/src/box/sql/vdbe.c @@ -3099,6 +3099,11 @@ case OP_IteratorOpen: else space = aMem[pOp->p3].u.p; assert(space != NULL); + if (access_check_space(space, PRIV_R) != 0) { + rc = SQL_TARANTOOL_ERROR; + goto abort_due_to_error; + } + struct index *index = space_index(space, pOp->p2); assert(index != NULL); assert(pOp->p1 >= 0); diff --git a/test/sql/gh-2362-select-access-rights.result b/test/sql/gh-2362-select-access-rights.result new file mode 100644 index 0000000..b42ee36 --- /dev/null +++ b/test/sql/gh-2362-select-access-rights.result @@ -0,0 +1,110 @@ +test_run = require('test_run').new() +--- +... +engine = test_run:get_cfg('engine') +--- +... +nb = require('net.box') +--- +... +box.sql.execute("PRAGMA sql_default_engine='"..engine.."'") +--- +... +box.sql.execute("CREATE TABLE t1 (s1 INT PRIMARY KEY, s2 INT UNIQUE);") +--- +... +box.sql.execute("CREATE TABLE t2 (s1 INT PRIMARY KEY);") +--- +... +box.sql.execute("INSERT INTO t1 VALUES (1, 1);") +--- +... +box.sql.execute("INSERT INTO t2 VALUES (1);") +--- +... +box.schema.user.grant('guest','read', 'space', 'T1') +--- +... +c = nb.connect(box.cfg.listen) +--- +... +c:execute("SELECT * FROM t1;") +--- +- metadata: + - name: S1 + - name: S2 + rows: + - [1, 1] +... +box.schema.user.revoke('guest','read', 'space', 'T1') +--- +... +c = nb.connect(box.cfg.listen) +--- +... +c:execute("SELECT * FROM t1;") +--- +- error: 'Failed to execute SQL statement: Read access to space ''T1'' is denied for + user ''guest''' +... +box.schema.user.grant('guest','read', 'space', 'T2') +--- +... +c = nb.connect(box.cfg.listen) +--- +... +c:execute('SELECT * FROM t1, t2 WHERE t1.s1 = t2.s1') +--- +- error: 'Failed to execute SQL statement: Read access to space ''T1'' is denied for + user ''guest''' +... +box.sql.execute("CREATE VIEW v AS SELECT * FROM t1") +--- +... +box.schema.user.grant('guest','read', 'space', 'V') +--- +... +v = nb.connect(box.cfg.listen) +--- +... +c:execute('SELECT * FROM v') +--- +- error: 'Failed to execute SQL statement: Read access to space ''T1'' is denied for + user ''guest''' +... +box.sql.execute('CREATE TABLE t3 (s1 INT PRIMARY KEY, fk INT, FOREIGN KEY (fk) REFERENCES t1(s2))') +--- +... +box.schema.user.grant('guest','read','space', 'T3') +--- +... +v = nb.connect(box.cfg.listen) +--- +... +c:execute('INSERT INTO t3 VALUES (1, 1)') +--- +- error: 'Failed to execute SQL statement: Read access to space ''T1'' is denied for + user ''guest''' +... +-- Cleanup +box.schema.user.revoke('guest','read','space', 'V') +--- +... +box.schema.user.revoke('guest','read','space', 'T2') +--- +... +box.schema.user.revoke('guest','read','space', 'T3') +--- +... +box.sql.execute('DROP VIEW v') +--- +... +box.sql.execute('DROP TABLE t3') +--- +... +box.sql.execute('DROP TABLE t2') +--- +... +box.sql.execute("DROP TABLE t1") +--- +... diff --git a/test/sql/gh-2362-select-access-rights.test.lua b/test/sql/gh-2362-select-access-rights.test.lua new file mode 100644 index 0000000..9c50e19 --- /dev/null +++ b/test/sql/gh-2362-select-access-rights.test.lua @@ -0,0 +1,42 @@ +test_run = require('test_run').new() +engine = test_run:get_cfg('engine') +nb = require('net.box') + +box.sql.execute("PRAGMA sql_default_engine='"..engine.."'") +box.sql.execute("CREATE TABLE t1 (s1 INT PRIMARY KEY, s2 INT UNIQUE);") +box.sql.execute("CREATE TABLE t2 (s1 INT PRIMARY KEY);") +box.sql.execute("INSERT INTO t1 VALUES (1, 1);") +box.sql.execute("INSERT INTO t2 VALUES (1);") + +box.schema.user.grant('guest','read', 'space', 'T1') +c = nb.connect(box.cfg.listen) +c:execute("SELECT * FROM t1;") + +box.schema.user.revoke('guest','read', 'space', 'T1') +c = nb.connect(box.cfg.listen) +c:execute("SELECT * FROM t1;") + +box.schema.user.grant('guest','read', 'space', 'T2') +c = nb.connect(box.cfg.listen) +c:execute('SELECT * FROM t1, t2 WHERE t1.s1 = t2.s1') + +box.sql.execute("CREATE VIEW v AS SELECT * FROM t1") + +box.schema.user.grant('guest','read', 'space', 'V') +v = nb.connect(box.cfg.listen) +c:execute('SELECT * FROM v') + +box.sql.execute('CREATE TABLE t3 (s1 INT PRIMARY KEY, fk INT, FOREIGN KEY (fk) REFERENCES t1(s2))') +box.schema.user.grant('guest','read','space', 'T3') +v = nb.connect(box.cfg.listen) +c:execute('INSERT INTO t3 VALUES (1, 1)') + +-- Cleanup +box.schema.user.revoke('guest','read','space', 'V') +box.schema.user.revoke('guest','read','space', 'T2') +box.schema.user.revoke('guest','read','space', 'T3') + +box.sql.execute('DROP VIEW v') +box.sql.execute('DROP TABLE t3') +box.sql.execute('DROP TABLE t2') +box.sql.execute("DROP TABLE t1") -- 2.11.0