Below is the list of changes that have just been committed into a local
5.0 repository of gluh. When gluh does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet
1.1799 05/03/05 14:35:32 gluh@stripped +8 -0
WL2131: Access control for SHOW ... PROCEDURE|FUNCTION ...
sql/sql_show.cc
1.222 05/03/05 14:34:18 gluh@stripped +33 -19
WL2131: Access control for SHOW ... PROCEDURE|FUNCTION ...
sql/sql_parse.cc
1.412 05/03/05 14:34:18 gluh@stripped +32 -0
WL2131: Access control for SHOW ... PROCEDURE|FUNCTION ...
sql/sql_acl.h
1.39 05/03/05 14:34:18 gluh@stripped +4 -0
WL2131: Access control for SHOW ... PROCEDURE|FUNCTION ...
sql/sql_acl.cc
1.140 05/03/05 14:34:18 gluh@stripped +31 -0
WL2131: Access control for SHOW ... PROCEDURE|FUNCTION ...
sql/sp_head.cc
1.119 05/03/05 14:34:18 gluh@stripped +33 -2
WL2131: Access control for SHOW ... PROCEDURE|FUNCTION ...
sql/mysql_priv.h
1.271 05/03/05 14:34:18 gluh@stripped +1 -0
WL2131: Access control for SHOW ... PROCEDURE|FUNCTION ...
mysql-test/t/information_schema.test
1.27 05/03/05 14:34:18 gluh@stripped +30 -7
WL2131: Access control for SHOW ... PROCEDURE|FUNCTION ...
mysql-test/r/information_schema.result
1.35 05/03/05 14:34:18 gluh@stripped +42 -3
WL2131: Access control for SHOW ... PROCEDURE|FUNCTION ...
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: gluh
# Host: gluh.mysql.r18.ru
# Root: /home/gluh/MySQL/mysql-5.0
--- 1.270/sql/mysql_priv.h Fri Mar 4 17:00:59 2005
+++ 1.271/sql/mysql_priv.h Sat Mar 5 14:34:18 2005
@@ -453,6 +453,7 @@
bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table);
bool check_merge_table_access(THD *thd, char *db,
TABLE_LIST *table_list);
+bool check_some_routine_access(THD *thd, char *db, char *name);
bool multi_update_precheck(THD *thd, TABLE_LIST *tables);
bool multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count);
bool mysql_multi_update_prepare(THD *thd);
--- 1.139/sql/sql_acl.cc Fri Mar 4 17:00:59 2005
+++ 1.140/sql/sql_acl.cc Sat Mar 5 14:34:18 2005
@@ -3583,6 +3583,37 @@
}
+/*
+ Check if routine has any of the
+ procedure level grants
+
+ SYNPOSIS
+ bool check_routine_level_acl()
+ thd Thread handler
+ db Database name
+ name Routine name
+
+ RETURN
+ 1 error
+ 0 Ok
+*/
+
+bool check_routine_level_acl(THD *thd, char *db, char *name)
+{
+ bool no_routine_acl= 1;
+ if (grant_option)
+ {
+ GRANT_NAME *grant_proc;
+ rw_rdlock(&LOCK_grant);
+ if ((grant_proc= proc_hash_search(thd->priv_host, thd->ip, db,
+ thd->priv_user, name, 0)))
+ no_routine_acl= !(grant_proc->privs & SHOW_PROC_ACLS);
+ rw_unlock(&LOCK_grant);
+ }
+ return no_routine_acl;
+}
+
+
/*****************************************************************************
Functions to retrieve the grant for a table/column (for SHOW functions)
*****************************************************************************/
--- 1.38/sql/sql_acl.h Mon Jan 24 20:57:32 2005
+++ 1.39/sql/sql_acl.h Sat Mar 5 14:34:18 2005
@@ -63,6 +63,9 @@
#define PROC_ACLS \
(ALTER_PROC_ACL | EXECUTE_ACL | GRANT_ACL)
+#define SHOW_PROC_ACLS \
+(ALTER_PROC_ACL | EXECUTE_ACL | CREATE_PROC_ACL)
+
#define GLOBAL_ACLS \
(SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \
RELOAD_ACL | SHUTDOWN_ACL | PROCESS_ACL | FILE_ACL | GRANT_ACL | \
@@ -216,6 +219,7 @@
const char *db, const char *table);
bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name);
bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name);
+bool check_routine_level_acl(THD *thd, char *db, char *name);
#ifdef NO_EMBEDDED_ACCESS_CHECKS
#define check_grant(A,B,C,D,E,F) 0
--- 1.411/sql/sql_parse.cc Fri Mar 4 17:46:41 2005
+++ 1.412/sql/sql_parse.cc Sat Mar 5 14:34:18 2005
@@ -4745,6 +4745,38 @@
return FALSE;
}
+
+/*
+ Check if the routine has any of the routine privileges
+
+ SYNOPSIS
+ check_some_routine_access()
+ thd Thread handler
+ db Database name
+ name Routine name
+
+ RETURN
+ 0 ok
+ 1 error
+*/
+
+bool check_some_routine_access(THD *thd, char *db, char *name)
+{
+ ulong save_priv;
+ if (thd->master_access & SHOW_PROC_ACLS)
+ return FALSE;
+ if (!check_access(thd, SHOW_PROC_ACLS, db, &save_priv, 0, 1) ||
+ (save_priv & SHOW_PROC_ACLS))
+ return FALSE;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (grant_option)
+ return check_routine_level_acl(thd, db, name);
+#endif
+
+ return FALSE;
+}
+
+
/*
Check if the given table has any of the asked privileges
--- 1.221/sql/sql_show.cc Thu Mar 3 19:20:09 2005
+++ 1.222/sql/sql_show.cc Sat Mar 5 14:34:18 2005
@@ -2468,32 +2468,41 @@
}
-void store_schema_proc(THD *thd, TABLE *table,
- TABLE *proc_table,
- const char *wild)
+void store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
+ const char *wild, bool full_access, const char *sp_user)
{
String tmp_string;
TIME time;
LEX *lex= thd->lex;
CHARSET_INFO *cs= system_charset_info;
- restore_record(table, s->default_values);
+ const char *sp_db, *sp_name, *definer;
+ sp_db= get_field(thd->mem_root, proc_table->field[0]);
+ sp_name= get_field(thd->mem_root, proc_table->field[1]);
+ definer= get_field(thd->mem_root, proc_table->field[11]);
+ if (!full_access)
+ full_access= !strcmp(sp_user, definer);
+ if (!full_access)
+ {
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (check_some_routine_access(thd, (char * )sp_db, (char * )sp_name))
+ return;
+#endif
+ }
+
if (lex->orig_sql_command == SQLCOM_SHOW_STATUS_PROC &&
proc_table->field[2]->val_int() == TYPE_ENUM_PROCEDURE ||
lex->orig_sql_command == SQLCOM_SHOW_STATUS_FUNC &&
proc_table->field[2]->val_int() == TYPE_ENUM_FUNCTION ||
lex->orig_sql_command == SQLCOM_END)
{
- tmp_string.length(0);
- get_field(thd->mem_root, proc_table->field[1], &tmp_string);
- if (!wild || !wild[0] || !wild_compare(tmp_string.ptr(), wild, 0))
+ restore_record(table, s->default_values);
+ if (!wild || !wild[0] || !wild_compare(sp_name, wild, 0))
{
- table->field[3]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ table->field[3]->store(sp_name, strlen(sp_name), cs);
tmp_string.length(0);
get_field(thd->mem_root, proc_table->field[3], &tmp_string);
table->field[0]->store(tmp_string.ptr(), tmp_string.length(), cs);
- tmp_string.length(0);
- get_field(thd->mem_root, proc_table->field[0], &tmp_string);
- table->field[2]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ table->field[2]->store(sp_db, strlen(sp_db), cs);
tmp_string.length(0);
get_field(thd->mem_root, proc_table->field[2], &tmp_string);
table->field[4]->store(tmp_string.ptr(), tmp_string.length(), cs);
@@ -2504,10 +2513,13 @@
table->field[5]->store(tmp_string.ptr(), tmp_string.length(), cs);
table->field[5]->set_notnull();
}
+ if (full_access)
+ {
+ tmp_string.length(0);
+ get_field(thd->mem_root, proc_table->field[10], &tmp_string);
+ table->field[7]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ }
table->field[6]->store("SQL", 3, cs);
- tmp_string.length(0);
- get_field(thd->mem_root, proc_table->field[10], &tmp_string);
- table->field[7]->store(tmp_string.ptr(), tmp_string.length(), cs);
table->field[10]->store("SQL", 3, cs);
tmp_string.length(0);
get_field(thd->mem_root, proc_table->field[6], &tmp_string);
@@ -2531,9 +2543,7 @@
tmp_string.length(0);
get_field(thd->mem_root, proc_table->field[15], &tmp_string);
table->field[18]->store(tmp_string.ptr(), tmp_string.length(), cs);
- tmp_string.length(0);
- get_field(thd->mem_root, proc_table->field[11], &tmp_string);
- table->field[19]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ table->field[19]->store(definer, strlen(definer), cs);
table->file->write_row(table->record[0]);
}
}
@@ -2547,14 +2557,18 @@
const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
int res= 0;
TABLE *table= tables->table, *old_open_tables= thd->open_tables;
+ bool full_access;
+ char definer[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
DBUG_ENTER("fill_schema_proc");
+ strxmov(definer, thd->priv_user, "@", thd->priv_host, NullS);
bzero((char*) &proc_tables,sizeof(proc_tables));
proc_tables.db= (char*) "mysql";
proc_tables.db_length= 5;
proc_tables.table_name= proc_tables.alias= (char*) "proc";
proc_tables.table_name_length= 4;
proc_tables.lock_type= TL_READ;
+ full_access= !check_table_access(thd, SELECT_ACL, &proc_tables, 1);
if (!(proc_table= open_ltable(thd, &proc_tables, TL_READ)))
{
DBUG_RETURN(1);
@@ -2565,9 +2579,9 @@
res= (res == HA_ERR_END_OF_FILE) ? 0 : 1;
goto err;
}
- store_schema_proc(thd, table, proc_table, wild);
+ store_schema_proc(thd, table, proc_table, wild, full_access, definer);
while (!proc_table->file->index_next(proc_table->record[0]))
- store_schema_proc(thd, table, proc_table, wild);
+ store_schema_proc(thd, table, proc_table, wild, full_access, definer);
err:
proc_table->file->ha_index_end();
--- 1.34/mysql-test/r/information_schema.result Thu Mar 3 19:20:09 2005
+++ 1.35/mysql-test/r/information_schema.result Sat Mar 5 14:34:18 2005
@@ -1,7 +1,8 @@
show variables where variable_name like "skip_show_database";
Variable_name Value
skip_show_database OFF
-grant all privileges on test.* to mysqltest_1@localhost;
+grant select, update, execute on test.* to mysqltest_2@localhost;
+grant select, update on test.* to mysqltest_1@localhost;
select * from information_schema.SCHEMATA where schema_name > 'm';
CATALOG_NAME SCHEMA_NAME DEFAULT_CHARACTER_SET_NAME SQL_PATH
NULL mysql latin1 NULL
@@ -229,6 +230,44 @@
select count(*) from information_schema.ROUTINES;
count(*)
2
+select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES;
+ROUTINE_NAME ROUTINE_DEFINITION
+show create function sub1;
+ERROR 42000: FUNCTION sub1 does not exist
+select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES;
+ROUTINE_NAME ROUTINE_DEFINITION
+sel2
+sub1
+grant all privileges on test.* to mysqltest_1@localhost;
+select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES;
+ROUTINE_NAME ROUTINE_DEFINITION
+sel2
+sub1
+create function sub2(i int) returns int
+return i+1;
+select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES;
+ROUTINE_NAME ROUTINE_DEFINITION
+sel2
+sub1
+sub2 return i+1
+show create procedure sel2;
+Procedure sql_mode Create Procedure
+sel2
+show create function sub1;
+Function sql_mode Create Function
+sub1
+show create function sub2;
+Function sql_mode Create Function
+sub2 CREATE FUNCTION `test`.`sub2`(i int) RETURNS int
+return i+1
+drop function sub2;
+show create procedure sel2;
+Procedure sql_mode Create Procedure
+sel2 CREATE PROCEDURE `test`.`sel2`()
+begin
+select * from t1;
+select * from t2;
+end
create view v0 (c) as select schema_name from information_schema.schemata;
select * from v0;
c
@@ -311,8 +350,8 @@
'mysqltest_1'@'localhost' NULL test t1 a INSERT NO
'mysqltest_1'@'localhost' NULL test t1 a UPDATE NO
'mysqltest_1'@'localhost' NULL test t1 a REFERENCES NO
-delete from mysql.user where user='mysqltest_1';
-delete from mysql.db where user='mysqltest_1';
+delete from mysql.user where user='mysqltest_1' or user='mysqltest_2';
+delete from mysql.db where user='mysqltest_1' or user='mysqltest_2';
delete from mysql.tables_priv where user='mysqltest_1';
delete from mysql.columns_priv where user='mysqltest_1';
flush privileges;
--- 1.26/mysql-test/t/information_schema.test Thu Mar 3 19:20:09 2005
+++ 1.27/mysql-test/t/information_schema.test Sat Mar 5 14:34:18 2005
@@ -3,7 +3,8 @@
# show databases
show variables where variable_name like "skip_show_database";
-grant all privileges on test.* to mysqltest_1@localhost;
+grant select, update, execute on test.* to mysqltest_2@localhost;
+grant select, update on test.* to mysqltest_1@localhost;
select * from information_schema.SCHEMATA where schema_name > 'm';
select schema_name from information_schema.schemata;
@@ -104,6 +105,30 @@
mysql.proc b where a.ROUTINE_NAME = convert(b.name using utf8);
select count(*) from information_schema.ROUTINES;
+connect (user1,localhost,mysqltest_1,,);
+connect (user3,localhost,mysqltest_2,,);
+connection user1;
+select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES;
+--error 1305
+show create function sub1;
+connection user3;
+select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES;
+connection default;
+grant all privileges on test.* to mysqltest_1@localhost;
+connect (user2,localhost,mysqltest_1,,);
+connection user2;
+select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES;
+create function sub2(i int) returns int
+ return i+1;
+select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES;
+show create procedure sel2;
+show create function sub1;
+show create function sub2;
+connection default;
+disconnect user1;
+drop function sub2;
+show create procedure sel2;
+
#
# Test for views
#
@@ -138,8 +163,8 @@
select * from information_schema.SCHEMA_PRIVILEGES where grantee like '%mysqltest_1%';
select * from information_schema.TABLE_PRIVILEGES where grantee like '%mysqltest_1%';
select * from information_schema.COLUMN_PRIVILEGES where grantee like '%mysqltest_1%';
-delete from mysql.user where user='mysqltest_1';
-delete from mysql.db where user='mysqltest_1';
+delete from mysql.user where user='mysqltest_1' or user='mysqltest_2';
+delete from mysql.db where user='mysqltest_1' or user='mysqltest_2';
delete from mysql.tables_priv where user='mysqltest_1';
delete from mysql.columns_priv where user='mysqltest_1';
flush privileges;
@@ -160,13 +185,11 @@
select * from information_schema.KEY_COLUMN_USAGE where
TABLE_SCHEMA= "test";
-
-connect (user1,localhost,mysqltest_1,,);
-connection user1;
+connection user2;
select table_name from information_schema.TABLES where table_schema like "test%";
select table_name,column_name from information_schema.COLUMNS where table_schema like
"test%";
select ROUTINE_NAME from information_schema.ROUTINES;
-disconnect user1;
+disconnect user2;
connection default;
delete from mysql.user where user='mysqltest_1';
drop table t1;
--- 1.118/sql/sp_head.cc Fri Mar 4 17:46:41 2005
+++ 1.119/sql/sp_head.cc Sat Mar 5 14:34:18 2005
@@ -1004,6 +1004,27 @@
}
+bool check_show_routine_acceess(THD *thd, sp_head *sp, bool *full_access)
+{
+ TABLE_LIST tables;
+ bzero((char*) &tables,sizeof(tables));
+ tables.db= (char*) "mysql";
+ tables.table_name= tables.alias= (char*) "proc";
+ *full_access= !check_table_access(thd, SELECT_ACL, &tables, 1);
+ if (!(*full_access))
+ *full_access= (!strcmp(sp->m_definer_user.str, thd->priv_user) &&
+ !strcmp(sp->m_definer_host.str, thd->priv_host));
+ if (!(*full_access))
+ {
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ return check_some_routine_access(thd, (char * )sp->m_db.str,
+ (char * ) sp->m_name.str);
+#endif
+ }
+ return 0;
+}
+
+
int
sp_head::show_create_procedure(THD *thd)
{
@@ -1016,11 +1037,15 @@
sys_var *sql_mode_var;
byte *sql_mode_str;
ulong sql_mode_len;
+ bool full_access;
DBUG_ENTER("sp_head::show_create_procedure");
DBUG_PRINT("info", ("procedure %s", m_name.str));
LINT_INIT(sql_mode_str);
LINT_INIT(sql_mode_len);
+
+ if (check_show_routine_acceess(thd, this, &full_access))
+ return 1;
old_sql_mode= thd->variables.sql_mode;
thd->variables.sql_mode= m_sql_mode;
@@ -1047,7 +1072,8 @@
protocol->store(m_name.str, m_name.length, system_charset_info);
if (sql_mode_var)
protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
- protocol->store(m_defstr.str, m_defstr.length, system_charset_info);
+ if (full_access)
+ protocol->store(m_defstr.str, m_defstr.length, system_charset_info);
res= protocol->write();
send_eof(thd);
@@ -1085,11 +1111,15 @@
sys_var *sql_mode_var;
byte *sql_mode_str;
ulong sql_mode_len;
+ bool full_access;
DBUG_ENTER("sp_head::show_create_function");
DBUG_PRINT("info", ("procedure %s", m_name.str));
LINT_INIT(sql_mode_str);
LINT_INIT(sql_mode_len);
+ if (check_show_routine_acceess(thd, this, &full_access))
+ return 1;
+
old_sql_mode= thd->variables.sql_mode;
thd->variables.sql_mode= m_sql_mode;
sql_mode_var= find_sys_var("SQL_MODE", 8);
@@ -1114,7 +1144,8 @@
protocol->store(m_name.str, m_name.length, system_charset_info);
if (sql_mode_var)
protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
- protocol->store(m_defstr.str, m_defstr.length, system_charset_info);
+ if (full_access)
+ protocol->store(m_defstr.str, m_defstr.length, system_charset_info);
res= protocol->write();
send_eof(thd);
| Thread |
|---|
| • bk commit into 5.0 tree (gluh:1.1799) | gluh | 5 Mar |