commit e5834e43350becf3186a0428bec07535a44111de from: Kirill Yukhin via: Vladimir Davydov date: Fri Oct 26 20:34:32 2018 UTC sql: check read access while executing SQL query 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 commit - 5b7cc2945717570c6bf0a13e6207303e798dc30b commit + e5834e43350becf3186a0428bec07535a44111de blob - 7c1015cf9cd985e6ad23d4f9ead1fad42cb3d907 blob + 10b58b4266131a2a04672c95e5034d5343a87aea --- src/box/sql/vdbe.c +++ 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); blob - /dev/null blob + b42ee360c7311c4e91ab9a8f69d61d9a1162aeef (mode 644) --- /dev/null +++ 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") +--- +... blob - /dev/null blob + 9c50e19467c4c25cbce53c980df31d1a58b18e5b (mode 644) --- /dev/null +++ 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")