MDEV-32500 Information schema leaks table names and structure to unauthorized users
standard table KEY_COLUMN_USAGE should only show keys where a user has some privileges on every column of the key standard table TABLE_CONSTRAINTS should show tables where a user has any non-SELECT privilege on the table or on any column of the table standard table REFERENTIAL_CONSTRAINTS is defined in terms of TABLE_CONSTRAINTS, so the same rule applies. If the user has no rights to see the REFERENCED_TABLE_NAME value, it should be NULL SHOW INDEX (and STATISTICS table) is non-standard, but it seems reasonable to use the same logic as for KEY_COLUMN_USAGE.
This commit is contained in:
parent
2eee0e9b89
commit
547dfc0e01
@ -101,7 +101,6 @@ ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table
|
||||
** SHOW INDEX FROM t6 will succeed because there exist a privilege on a column combination on t6.
|
||||
SHOW INDEX FROM t6;
|
||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
|
||||
t6 1 i 1 s1 A NULL NULL NULL YES BTREE
|
||||
** CHECK TABLE requires any privilege on any column combination and should succeed for t6:
|
||||
CHECK TABLE t6;
|
||||
Table Op Msg_type Msg_text
|
||||
|
@ -262,8 +262,8 @@ set global sql_mode=default;
|
||||
create user foo@localhost;
|
||||
grant select on test.* to foo@localhost;
|
||||
create procedure rootonly() select 1;
|
||||
create sql security definer view v1d as select current_user(),user from information_schema.processlist;
|
||||
create sql security invoker view v1i as select current_user(),user from information_schema.processlist;
|
||||
create sql security definer view v1d as select current_user(),user from information_schema.processlist where command!='daemon';
|
||||
create sql security invoker view v1i as select current_user(),user from information_schema.processlist where command!='daemon';
|
||||
create sql security definer view v2d as select table_name from information_schema.tables where table_schema='mysql' and table_name like '%user%';
|
||||
create sql security invoker view v2i as select table_name from information_schema.tables where table_schema='mysql' and table_name like '%user%';
|
||||
create sql security definer view v3d as select schema_name from information_schema.schemata where schema_name like '%mysql%';
|
||||
@ -341,3 +341,47 @@ drop procedure rootonly;
|
||||
#
|
||||
# End of 10.2 tests
|
||||
#
|
||||
#
|
||||
# MDEV-32500 Information schema leaks table names and structure to unauthorized users
|
||||
#
|
||||
create database db;
|
||||
create table db.t1 (x int, key(x)) engine=InnoDB;
|
||||
create table db.t2 (a int, b int, c int, unique(b), check(c>b), foreign key(c) references db.t1(x)) engine=InnoDB;
|
||||
create table db.t3 (d int, e int, f int, unique(e), check(f>e), foreign key(f) references db.t1(x),
|
||||
foreign key(e) references db.t2(b),
|
||||
foreign key(d) references db.t3(f)
|
||||
) engine=InnoDB;
|
||||
create user u@localhost;
|
||||
grant select (a) on db.t2 to u@localhost;
|
||||
grant update (d) on db.t3 to u@localhost;
|
||||
connect con1,localhost,u,,db;
|
||||
select table_name, column_name from information_schema.columns where table_name like 't_';
|
||||
table_name column_name
|
||||
t2 a
|
||||
t3 d
|
||||
select table_name, column_name from information_schema.key_column_usage where table_name like 't_';
|
||||
table_name column_name
|
||||
select table_name, unique_constraint_name, referenced_table_name from information_schema.referential_constraints where table_name like 't_';
|
||||
table_name unique_constraint_name referenced_table_name
|
||||
t3 x NULL
|
||||
t3 b NULL
|
||||
t3 f t3
|
||||
select table_name, constraint_name, constraint_type from information_schema.table_constraints where table_name like 't_';
|
||||
table_name constraint_name constraint_type
|
||||
t3 e UNIQUE
|
||||
t3 CONSTRAINT_1 CHECK
|
||||
t3 t3_ibfk_1 FOREIGN KEY
|
||||
t3 t3_ibfk_2 FOREIGN KEY
|
||||
t3 t3_ibfk_3 FOREIGN KEY
|
||||
show index in t2;
|
||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
|
||||
show index in t3;
|
||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
|
||||
t3 1 d 1 d A 0 NULL NULL YES BTREE
|
||||
disconnect con1;
|
||||
connection default;
|
||||
drop user u@localhost;
|
||||
drop database db;
|
||||
#
|
||||
# End of 10.4 tests
|
||||
#
|
||||
|
@ -1,7 +1,7 @@
|
||||
# this test mostly test privilege control (what doesn't work
|
||||
# in the embedded server by default). So skip the test in embedded-server mode.
|
||||
-- source include/not_embedded.inc
|
||||
|
||||
-- source include/have_innodb.inc
|
||||
-- source include/testdb_only.inc
|
||||
|
||||
set local sql_mode="";
|
||||
@ -256,8 +256,8 @@ set global sql_mode=default;
|
||||
create user foo@localhost;
|
||||
grant select on test.* to foo@localhost;
|
||||
create procedure rootonly() select 1;
|
||||
create sql security definer view v1d as select current_user(),user from information_schema.processlist;
|
||||
create sql security invoker view v1i as select current_user(),user from information_schema.processlist;
|
||||
create sql security definer view v1d as select current_user(),user from information_schema.processlist where command!='daemon';
|
||||
create sql security invoker view v1i as select current_user(),user from information_schema.processlist where command!='daemon';
|
||||
create sql security definer view v2d as select table_name from information_schema.tables where table_schema='mysql' and table_name like '%user%';
|
||||
create sql security invoker view v2i as select table_name from information_schema.tables where table_schema='mysql' and table_name like '%user%';
|
||||
create sql security definer view v3d as select schema_name from information_schema.schemata where schema_name like '%mysql%';
|
||||
@ -297,3 +297,36 @@ drop procedure rootonly;
|
||||
--echo #
|
||||
--echo # End of 10.2 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-32500 Information schema leaks table names and structure to unauthorized users
|
||||
--echo #
|
||||
create database db;
|
||||
create table db.t1 (x int, key(x)) engine=InnoDB;
|
||||
create table db.t2 (a int, b int, c int, unique(b), check(c>b), foreign key(c) references db.t1(x)) engine=InnoDB;
|
||||
create table db.t3 (d int, e int, f int, unique(e), check(f>e), foreign key(f) references db.t1(x),
|
||||
foreign key(e) references db.t2(b),
|
||||
foreign key(d) references db.t3(f)
|
||||
) engine=InnoDB;
|
||||
|
||||
create user u@localhost;
|
||||
grant select (a) on db.t2 to u@localhost;
|
||||
grant update (d) on db.t3 to u@localhost;
|
||||
|
||||
--connect con1,localhost,u,,db
|
||||
--sorted_result
|
||||
select table_name, column_name from information_schema.columns where table_name like 't_';
|
||||
select table_name, column_name from information_schema.key_column_usage where table_name like 't_';
|
||||
select table_name, unique_constraint_name, referenced_table_name from information_schema.referential_constraints where table_name like 't_';
|
||||
select table_name, constraint_name, constraint_type from information_schema.table_constraints where table_name like 't_';
|
||||
show index in t2;
|
||||
show index in t3;
|
||||
|
||||
--disconnect con1
|
||||
--connection default
|
||||
drop user u@localhost;
|
||||
drop database db;
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.4 tests
|
||||
--echo #
|
||||
|
@ -287,7 +287,7 @@ def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_NAME 3 NULL NO varchar
|
||||
def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_SCHEMA 2 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL
|
||||
def information_schema REFERENTIAL_CONSTRAINTS DELETE_RULE 9 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL
|
||||
def information_schema REFERENTIAL_CONSTRAINTS MATCH_OPTION 7 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL
|
||||
def information_schema REFERENTIAL_CONSTRAINTS REFERENCED_TABLE_NAME 11 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL
|
||||
def information_schema REFERENTIAL_CONSTRAINTS REFERENCED_TABLE_NAME 11 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL
|
||||
def information_schema REFERENTIAL_CONSTRAINTS TABLE_NAME 10 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL
|
||||
def information_schema REFERENTIAL_CONSTRAINTS UNIQUE_CONSTRAINT_CATALOG 4 NULL NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL
|
||||
def information_schema REFERENTIAL_CONSTRAINTS UNIQUE_CONSTRAINT_NAME 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL
|
||||
|
@ -287,7 +287,7 @@ def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_NAME 3 NULL NO varchar
|
||||
def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_SCHEMA 2 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL
|
||||
def information_schema REFERENTIAL_CONSTRAINTS DELETE_RULE 9 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL
|
||||
def information_schema REFERENTIAL_CONSTRAINTS MATCH_OPTION 7 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL
|
||||
def information_schema REFERENTIAL_CONSTRAINTS REFERENCED_TABLE_NAME 11 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL
|
||||
def information_schema REFERENTIAL_CONSTRAINTS REFERENCED_TABLE_NAME 11 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL
|
||||
def information_schema REFERENTIAL_CONSTRAINTS TABLE_NAME 10 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL
|
||||
def information_schema REFERENTIAL_CONSTRAINTS UNIQUE_CONSTRAINT_CATALOG 4 NULL NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL
|
||||
def information_schema REFERENTIAL_CONSTRAINTS UNIQUE_CONSTRAINT_NAME 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL
|
||||
|
@ -250,8 +250,6 @@ ORDER BY table_schema,table_name,index_name,seq_in_index,column_name;
|
||||
TABLE_CATALOG TABLE_SCHEMA TABLE_NAME NON_UNIQUE INDEX_SCHEMA INDEX_NAME SEQ_IN_INDEX COLUMN_NAME COLLATION CARDINALITY SUB_PART PACKED NULLABLE INDEX_TYPE COMMENT INDEX_COMMENT
|
||||
def db_datadict t1 1 db_datadict f2_ind 1 f2 NULL 0 NULL NULL YES HASH
|
||||
def db_datadict t1 0 db_datadict PRIMARY 1 f1 NULL 0 NULL NULL HASH
|
||||
def db_datadict_2 t3 1 db_datadict_2 f2f1_ind 1 f2 NULL NULL NULL NULL YES HASH
|
||||
def db_datadict_2 t3 1 db_datadict_2 f2f1_ind 2 f1 NULL 0 NULL NULL HASH
|
||||
def db_datadict_2 t3 0 db_datadict_2 f5 1 f5 NULL 0 NULL NULL YES HASH
|
||||
def db_datadict_2 t3 0 db_datadict_2 PRIMARY 1 f1 NULL 0 NULL NULL HASH
|
||||
SHOW GRANTS FOR 'testuser1'@'localhost';
|
||||
@ -282,8 +280,6 @@ SELECT * FROM information_schema.statistics
|
||||
WHERE table_schema LIKE 'db_datadict%'
|
||||
ORDER BY table_schema,table_name,index_name,seq_in_index,column_name;
|
||||
TABLE_CATALOG TABLE_SCHEMA TABLE_NAME NON_UNIQUE INDEX_SCHEMA INDEX_NAME SEQ_IN_INDEX COLUMN_NAME COLLATION CARDINALITY SUB_PART PACKED NULLABLE INDEX_TYPE COMMENT INDEX_COMMENT
|
||||
def db_datadict_2 t3 1 db_datadict_2 f2f1_ind 1 f2 NULL NULL NULL NULL YES HASH
|
||||
def db_datadict_2 t3 1 db_datadict_2 f2f1_ind 2 f1 NULL 0 NULL NULL HASH
|
||||
def db_datadict_2 t3 0 db_datadict_2 f5 1 f5 NULL 0 NULL NULL YES HASH
|
||||
def db_datadict_2 t3 0 db_datadict_2 PRIMARY 1 f1 NULL 0 NULL NULL HASH
|
||||
SHOW GRANTS FOR 'testuser1'@'localhost';
|
||||
|
@ -104,11 +104,11 @@ CREATE TABLE db_datadict.t2 (f1 BIGINT, f2 BIGINT, f3 BIGINT, f4 BIGINT,
|
||||
f5 BIGINT, f6 BIGINT, PRIMARY KEY (f1,f2))
|
||||
ENGINE = <some_engine_type>;
|
||||
CREATE USER 'testuser1'@'localhost';
|
||||
GRANT SELECT(f5) ON db_datadict.t1 TO 'testuser1'@'localhost';
|
||||
GRANT SELECT(f5), UPDATE(f6) ON db_datadict.t1 TO 'testuser1'@'localhost';
|
||||
SHOW GRANTS FOR 'testuser1'@'localhost';
|
||||
Grants for testuser1@localhost
|
||||
GRANT USAGE ON *.* TO `testuser1`@`localhost`
|
||||
GRANT SELECT (`f5`) ON `db_datadict`.`t1` TO `testuser1`@`localhost`
|
||||
GRANT SELECT (`f5`), UPDATE (`f6`) ON `db_datadict`.`t1` TO `testuser1`@`localhost`
|
||||
SELECT * FROM information_schema.table_constraints
|
||||
WHERE table_schema = 'db_datadict'
|
||||
ORDER BY table_schema,table_name, constraint_name;
|
||||
@ -132,7 +132,7 @@ connect testuser1, localhost, testuser1, , db_datadict;
|
||||
SHOW GRANTS FOR 'testuser1'@'localhost';
|
||||
Grants for testuser1@localhost
|
||||
GRANT USAGE ON *.* TO `testuser1`@`localhost`
|
||||
GRANT SELECT (`f5`) ON `db_datadict`.`t1` TO `testuser1`@`localhost`
|
||||
GRANT SELECT (`f5`), UPDATE (`f6`) ON `db_datadict`.`t1` TO `testuser1`@`localhost`
|
||||
SELECT * FROM information_schema.table_constraints
|
||||
WHERE table_schema = 'db_datadict'
|
||||
ORDER BY table_schema,table_name, constraint_name;
|
||||
@ -142,11 +142,6 @@ def db_datadict my_idx2 db_datadict t1 UNIQUE
|
||||
def db_datadict PRIMARY db_datadict t1 PRIMARY KEY
|
||||
SHOW INDEXES FROM db_datadict.t1;
|
||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
|
||||
t1 0 PRIMARY 1 f1 ### ### ### ### ### ### ###
|
||||
t1 0 PRIMARY 2 f2 ### ### ### ### ### ### ###
|
||||
t1 0 my_idx1 1 f6 ### ### ### ### ### ### ###
|
||||
t1 0 my_idx1 2 f1 ### ### ### ### ### ### ###
|
||||
t1 0 my_idx2 1 f3 ### ### ### ### ### ### ###
|
||||
SHOW INDEXES FROM db_datadict.t2;
|
||||
ERROR 42000: SELECT command denied to user 'testuser1'@'localhost' for table `db_datadict`.`t2`
|
||||
connection default;
|
||||
|
@ -99,7 +99,7 @@ CREATE TABLE db_datadict.t2 (f1 BIGINT, f2 BIGINT, f3 BIGINT, f4 BIGINT,
|
||||
ENGINE = $engine_type;
|
||||
|
||||
CREATE USER 'testuser1'@'localhost';
|
||||
GRANT SELECT(f5) ON db_datadict.t1 TO 'testuser1'@'localhost';
|
||||
GRANT SELECT(f5), UPDATE(f6) ON db_datadict.t1 TO 'testuser1'@'localhost';
|
||||
SHOW GRANTS FOR 'testuser1'@'localhost';
|
||||
|
||||
let $my_select = SELECT * FROM information_schema.table_constraints
|
||||
|
@ -7011,6 +7011,7 @@ static bool check_show_access(THD *thd, TABLE_LIST *table)
|
||||
FALSE, FALSE))
|
||||
return TRUE; /* Access denied */
|
||||
|
||||
thd->col_access= dst_table->grant.privilege; // for sql_show.cc
|
||||
/*
|
||||
Check_grant will grant access if there is any column privileges on
|
||||
all of the tables thanks to the fourth parameter (bool show_table).
|
||||
|
144
sql/sql_show.cc
144
sql/sql_show.cc
@ -6782,6 +6782,21 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables,
|
||||
HA_STATUS_CONST | HA_STATUS_TIME);
|
||||
set_statistics_for_table(thd, show_table);
|
||||
}
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
bool need_column_checks= false;
|
||||
/* we know that the table or at least some of the columns have
|
||||
necessary privileges, but the caller didn't pass down the GRANT_INFO
|
||||
object, so we have to rediscover everything again :( */
|
||||
if (!(thd->col_access & TABLE_ACLS))
|
||||
{
|
||||
check_grant(thd, SELECT_ACL, tables, 0, 1, 1);
|
||||
|
||||
if (!(tables->grant.privilege & TABLE_ACLS))
|
||||
need_column_checks= true;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint i=0 ; i < show_table->s->keys ; i++,key_info++)
|
||||
{
|
||||
if ((key_info->flags & HA_INVISIBLE_KEY) &&
|
||||
@ -6790,6 +6805,26 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables,
|
||||
KEY_PART_INFO *key_part= key_info->key_part;
|
||||
LEX_CSTRING *str;
|
||||
LEX_CSTRING unknown= {STRING_WITH_LEN("?unknown field?") };
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (need_column_checks)
|
||||
{
|
||||
uint j;
|
||||
for (j=0 ; j < key_info->user_defined_key_parts ; j++,key_part++)
|
||||
{
|
||||
uint access= get_column_grant(thd, &tables->grant, db_name->str,
|
||||
table_name->str,
|
||||
key_part->field->field_name.str);
|
||||
|
||||
if (!access)
|
||||
break;
|
||||
}
|
||||
if (j != key_info->user_defined_key_parts)
|
||||
continue;
|
||||
key_part= key_info->key_part;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint j=0 ; j < key_info->user_defined_key_parts ; j++,key_part++)
|
||||
{
|
||||
if (key_part->field->invisible >= INVISIBLE_SYSTEM &&
|
||||
@ -7102,6 +7137,21 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables,
|
||||
}
|
||||
else if (!tables->view)
|
||||
{
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
/* need any non-SELECT privilege on the table or any of its columns */
|
||||
const ulong need= TABLE_ACLS & ~SELECT_ACL;
|
||||
if (!(thd->col_access & need))
|
||||
{
|
||||
/* we know that the table or at least some of the columns have
|
||||
necessary privileges, but the caller didn't pass down the GRANT_INFO
|
||||
object, so we have to rediscover everything again :( */
|
||||
check_grant(thd, SELECT_ACL, tables, 0, 1, 1);
|
||||
|
||||
if (!(tables->grant.all_privilege() & need))
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
List<FOREIGN_KEY_INFO> f_key_list;
|
||||
TABLE *show_table= tables->table;
|
||||
KEY *key_info=show_table->s->key_info;
|
||||
@ -7299,12 +7349,46 @@ static int get_schema_key_column_usage_record(THD *thd, TABLE_LIST *tables,
|
||||
uint primary_key= show_table->s->primary_key;
|
||||
show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK |
|
||||
HA_STATUS_TIME);
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
bool need_column_checks= false;
|
||||
/* we know that the table or at least some of the columns have
|
||||
necessary privileges, but the caller didn't pass down the GRANT_INFO
|
||||
object, so we have to rediscover everything again :( */
|
||||
if (!(thd->col_access & TABLE_ACLS))
|
||||
{
|
||||
check_grant(thd, SELECT_ACL, tables, 0, 1, 1);
|
||||
|
||||
if (!(tables->grant.privilege & TABLE_ACLS))
|
||||
need_column_checks= true;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint i=0 ; i < show_table->s->keys ; i++, key_info++)
|
||||
{
|
||||
if (i != primary_key && !(key_info->flags & HA_NOSAME))
|
||||
continue;
|
||||
uint f_idx= 0;
|
||||
KEY_PART_INFO *key_part= key_info->key_part;
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (need_column_checks)
|
||||
{
|
||||
uint j;
|
||||
for (j=0 ; j < key_info->user_defined_key_parts ; j++,key_part++)
|
||||
{
|
||||
uint access= get_column_grant(thd, &tables->grant, db_name->str,
|
||||
table_name->str,
|
||||
key_part->field->field_name.str);
|
||||
|
||||
if (!access)
|
||||
break;
|
||||
}
|
||||
if (j != key_info->user_defined_key_parts)
|
||||
continue;
|
||||
key_part= key_info->key_part;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint j=0 ; j < key_info->user_defined_key_parts ; j++,key_part++)
|
||||
{
|
||||
f_idx++;
|
||||
@ -7329,6 +7413,23 @@ static int get_schema_key_column_usage_record(THD *thd, TABLE_LIST *tables,
|
||||
List_iterator_fast<LEX_CSTRING> it(f_key_info->foreign_fields),
|
||||
it1(f_key_info->referenced_fields);
|
||||
uint f_idx= 0;
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (need_column_checks)
|
||||
{
|
||||
while ((r_info= it1++))
|
||||
{
|
||||
uint access= get_column_grant(thd, &tables->grant, db_name->str,
|
||||
table_name->str, r_info->str);
|
||||
|
||||
if (!access)
|
||||
break;
|
||||
}
|
||||
if (!it1.at_end())
|
||||
continue;
|
||||
it1.rewind();
|
||||
}
|
||||
#endif
|
||||
while ((f_info= it++))
|
||||
{
|
||||
r_info= it1++;
|
||||
@ -8179,6 +8280,21 @@ get_referential_constraints_record(THD *thd, TABLE_LIST *tables,
|
||||
show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK |
|
||||
HA_STATUS_TIME);
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
/* need any non-SELECT privilege on the table or any of its columns */
|
||||
const ulong need= TABLE_ACLS & ~SELECT_ACL;
|
||||
if (!(thd->col_access & need))
|
||||
{
|
||||
/* we know that the table or at least some of the columns have
|
||||
necessary privileges, but the caller didn't pass down the GRANT_INFO
|
||||
object, so we have to rediscover everything again :( */
|
||||
check_grant(thd, SELECT_ACL, tables, 0, 1, 1);
|
||||
|
||||
if (!(tables->grant.all_privilege() & need))
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
show_table->file->get_foreign_key_list(thd, &f_key_list);
|
||||
FOREIGN_KEY_INFO *f_key_info;
|
||||
List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
|
||||
@ -8193,8 +8309,28 @@ get_referential_constraints_record(THD *thd, TABLE_LIST *tables,
|
||||
table->field[3]->store(STRING_WITH_LEN("def"), cs);
|
||||
table->field[4]->store(f_key_info->referenced_db->str,
|
||||
f_key_info->referenced_db->length, cs);
|
||||
table->field[10]->store(f_key_info->referenced_table->str,
|
||||
f_key_info->referenced_table->length, cs);
|
||||
bool show_ref_table= true;
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
/* need any non-SELECT privilege on the table or any of its columns */
|
||||
if (!(thd->col_access & need))
|
||||
{
|
||||
TABLE_LIST table_acl_check;
|
||||
bzero((char*) &table_acl_check, sizeof(table_acl_check));
|
||||
table_acl_check.db= *f_key_info->referenced_db;
|
||||
table_acl_check.table_name= *f_key_info->referenced_table;
|
||||
table_acl_check.grant.privilege= thd->col_access;
|
||||
check_grant(thd, SELECT_ACL, &table_acl_check, 0, 1, 1);
|
||||
|
||||
if (!(table_acl_check.grant.all_privilege() & need))
|
||||
show_ref_table= false;
|
||||
}
|
||||
#endif
|
||||
if (show_ref_table)
|
||||
{
|
||||
table->field[10]->set_notnull();
|
||||
table->field[10]->store(f_key_info->referenced_table->str,
|
||||
f_key_info->referenced_table->length, cs);
|
||||
}
|
||||
if (f_key_info->referenced_key_name)
|
||||
{
|
||||
table->field[5]->store(f_key_info->referenced_key_name->str,
|
||||
@ -9898,8 +10034,8 @@ ST_FIELD_INFO referential_constraints_fields_info[]=
|
||||
{"UPDATE_RULE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
|
||||
{"DELETE_RULE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
|
||||
{"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
|
||||
{"REFERENCED_TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
|
||||
OPEN_FULL_TABLE},
|
||||
{"REFERENCED_TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0,
|
||||
MY_I_S_MAYBE_NULL, 0, OPEN_FULL_TABLE},
|
||||
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user