From 63e56390a3f1a4f80642932a790ab74f28de8010 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Thu, 10 Sep 2009 03:18:29 -0600 Subject: WL#2110 (SIGNAL) WL#2265 (RESIGNAL) Manual merge of SIGNAL and RESIGNAL to mysql-trunk-signal, plus required dependencies. --- sql/sql_acl.cc | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'sql/sql_acl.cc') diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index ab18a2d1d04..9ab13438926 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -702,7 +702,7 @@ my_bool acl_reload(THD *thd) if (simple_open_n_lock_tables(thd, tables)) { sql_print_error("Fatal error: Can't open and lock privilege tables: %s", - thd->main_da.message()); + thd->stmt_da->message()); goto end; } @@ -6036,9 +6036,12 @@ public: virtual ~Silence_routine_definer_errors() {} - virtual bool handle_error(uint sql_errno, const char *message, - MYSQL_ERROR::enum_warning_level level, - THD *thd); + virtual bool handle_condition(THD *thd, + uint sql_errno, + const char* sqlstate, + MYSQL_ERROR::enum_warning_level level, + const char* msg, + MYSQL_ERROR ** cond_hdl); bool has_errors() { return is_grave; } @@ -6047,18 +6050,23 @@ private: }; bool -Silence_routine_definer_errors::handle_error(uint sql_errno, - const char *message, - MYSQL_ERROR::enum_warning_level level, - THD *thd) +Silence_routine_definer_errors::handle_condition( + THD *thd, + uint sql_errno, + const char*, + MYSQL_ERROR::enum_warning_level level, + const char* msg, + MYSQL_ERROR ** cond_hdl) { + *cond_hdl= NULL; if (level == MYSQL_ERROR::WARN_LEVEL_ERROR) { switch (sql_errno) { case ER_NONEXISTING_PROC_GRANT: /* Convert the error into a warning. */ - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, sql_errno, message); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + sql_errno, msg); return TRUE; default: is_grave= TRUE; -- cgit v1.2.1 From 13f09243e33141756b7d6012dbf49682bb1228ce Mon Sep 17 00:00:00 2001 From: Alexander Nozdrin Date: Sat, 10 Oct 2009 00:01:10 +0400 Subject: A backporting patch for WL#4300 (Define privileges for tablespaces). Original revision in 6.0: ------------------------------------------------------------ revno: 2630.13.11 committer: Alexander Nozdrin branch nick: 6.0-rt-wl4300 timestamp: Thu 2008-07-24 11:44:21 +0400 message: A patch for WL#4300: Define privileges for tablespaces. ------------------------------------------------------------ per-file messages: mysql-test/r/grant.result Update result file: new columm 'Create_tablespace_priv' has been added to mysql.user. mysql-test/r/ps.result Update result file: new columm 'Create_tablespace_priv' has been added to mysql.user. mysql-test/r/system_mysql_db.result Update result file: new columm 'Create_tablespace_priv' has been added to mysql.user. mysql-test/suite/falcon/r/falcon_tablespace_priv.result Test case for WL#4300. mysql-test/suite/falcon/t/falcon_tablespace_priv.test Test case for WL#4300. mysql-test/suite/ndb/r/ndb_dd_ddl.result Test case for WL#4300. mysql-test/suite/ndb/t/ndb_dd_ddl.test Test case for WL#4300. scripts/mysql_system_tables.sql New columm 'Create_tablespace_priv' has been added to mysql.user. scripts/mysql_system_tables_data.sql 'CREATE TABLESPACE' is granted by default to the root user. scripts/mysql_system_tables_fix.sql Grant 'CREATE TABLESPACE' privilege during system table upgrade if a user had SUPER privilege. sql/sql_acl.cc Added CREATE TABLESPACE privilege. sql/sql_acl.h Added CREATE TABLESPACE privilege. sql/sql_parse.cc Check global 'CREATE TABLESPACE' privilege for the following SQL statements: - CREATE | ALTER | DROP TABLESPACE - CREATE | ALTER | DROP LOGFILE GROUP sql/sql_show.cc Added CREATE TABLESPACE privilege. sql/sql_yacc.yy Added CREATE TABLESPACE privilege. --- sql/sql_acl.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sql/sql_acl.cc') diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 9ab13438926..224e4b4bffe 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -4467,13 +4467,13 @@ static const char *command_array[]= "ALTER", "SHOW DATABASES", "SUPER", "CREATE TEMPORARY TABLES", "LOCK TABLES", "EXECUTE", "REPLICATION SLAVE", "REPLICATION CLIENT", "CREATE VIEW", "SHOW VIEW", "CREATE ROUTINE", "ALTER ROUTINE", - "CREATE USER", "EVENT", "TRIGGER" + "CREATE USER", "EVENT", "TRIGGER", "CREATE TABLESPACE" }; static uint command_lengths[]= { 6, 6, 6, 6, 6, 4, 6, 8, 7, 4, 5, 10, 5, 5, 14, 5, 23, 11, 7, 17, 18, 11, 9, - 14, 13, 11, 5, 7 + 14, 13, 11, 5, 7, 17 }; -- cgit v1.2.1 From 9b41c7532d18b04d2f430932ad916886c77fbff6 Mon Sep 17 00:00:00 2001 From: Konstantin Osipov Date: Wed, 14 Oct 2009 20:37:38 +0400 Subject: Backport of: ---------------------------------------------------------- revno: 2617.22.5 committer: Konstantin Osipov branch nick: mysql-6.0-runtime timestamp: Tue 2009-01-27 05:08:48 +0300 message: Remove non-prefixed use of HASH. Always use my_hash_init(), my_hash_inited(), my_hash_search(), my_hash_element(), my_hash_delete(), my_hash_free() rather than non-prefixed counterparts (hash_init(), etc). Remove the backward-compatible defines. --- sql/sql_acl.cc | 126 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 65 insertions(+), 61 deletions(-) (limited to 'sql/sql_acl.cc') diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 224e4b4bffe..040c985560e 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -261,8 +261,8 @@ my_bool acl_init(bool dont_read_acl_tables) DBUG_ENTER("acl_init"); acl_cache= new hash_filo(ACL_CACHE_SIZE, 0, 0, - (hash_get_key) acl_entry_get_key, - (hash_free_key) free, + (my_hash_get_key) acl_entry_get_key, + (my_hash_free_key) free, lower_case_file_system ? system_charset_info : &my_charset_bin); if (dont_read_acl_tables) @@ -638,7 +638,7 @@ void acl_free(bool end) delete_dynamic(&acl_users); delete_dynamic(&acl_dbs); delete_dynamic(&acl_wild_hosts); - hash_free(&acl_check_hosts); + my_hash_free(&acl_check_hosts); if (!end) acl_cache->clear(1); /* purecov: inspected */ else @@ -714,7 +714,7 @@ my_bool acl_reload(THD *thd) old_acl_dbs=acl_dbs; old_mem=mem; delete_dynamic(&acl_wild_hosts); - hash_free(&acl_check_hosts); + my_hash_free(&acl_check_hosts); if ((return_val= acl_load(thd, tables))) { // Error. Revert to old list @@ -1429,8 +1429,8 @@ static void init_check_host(void) DBUG_ENTER("init_check_host"); VOID(my_init_dynamic_array(&acl_wild_hosts,sizeof(struct acl_host_and_ip), acl_users.elements,1)); - VOID(hash_init(&acl_check_hosts,system_charset_info,acl_users.elements,0,0, - (hash_get_key) check_get_key,0,0)); + VOID(my_hash_init(&acl_check_hosts,system_charset_info,acl_users.elements,0,0, + (my_hash_get_key) check_get_key,0,0)); if (!allow_all_hosts) { for (uint i=0 ; i < acl_users.elements ; i++) @@ -1452,8 +1452,9 @@ static void init_check_host(void) if (j == acl_wild_hosts.elements) // If new (void) push_dynamic(&acl_wild_hosts,(uchar*) &acl_user->host); } - else if (!hash_search(&acl_check_hosts,(uchar*) acl_user->host.hostname, - strlen(acl_user->host.hostname))) + else if (!my_hash_search(&acl_check_hosts,(uchar*) + acl_user->host.hostname, + strlen(acl_user->host.hostname))) { if (my_hash_insert(&acl_check_hosts,(uchar*) acl_user)) { // End of memory @@ -1480,7 +1481,7 @@ static void init_check_host(void) void rebuild_check_host(void) { delete_dynamic(&acl_wild_hosts); - hash_free(&acl_check_hosts); + my_hash_free(&acl_check_hosts); init_check_host(); } @@ -1493,8 +1494,8 @@ bool acl_check_host(const char *host, const char *ip) return 0; VOID(pthread_mutex_lock(&acl_cache->lock)); - if ((host && hash_search(&acl_check_hosts,(uchar*) host,strlen(host))) || - (ip && hash_search(&acl_check_hosts,(uchar*) ip, strlen(ip)))) + if ((host && my_hash_search(&acl_check_hosts,(uchar*) host,strlen(host))) || + (ip && my_hash_search(&acl_check_hosts,(uchar*) ip, strlen(ip)))) { VOID(pthread_mutex_unlock(&acl_cache->lock)); return 0; // Found host @@ -2298,8 +2299,8 @@ GRANT_TABLE::GRANT_TABLE(const char *h, const char *d,const char *u, const char *t, ulong p, ulong c) :GRANT_NAME(h,d,u,t,p), cols(c) { - (void) hash_init2(&hash_columns,4,system_charset_info, - 0,0,0, (hash_get_key) get_key_column,0,0); + (void) my_hash_init2(&hash_columns,4,system_charset_info, + 0,0,0, (my_hash_get_key) get_key_column,0,0); } @@ -2339,15 +2340,15 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) if (!db || !tname) { /* Wrong table row; Ignore it */ - hash_clear(&hash_columns); /* allow for destruction */ + my_hash_clear(&hash_columns); /* allow for destruction */ cols= 0; return; } cols= (ulong) form->field[7]->val_int(); cols = fix_rights_for_column(cols); - (void) hash_init2(&hash_columns,4,system_charset_info, - 0,0,0, (hash_get_key) get_key_column,0,0); + (void) my_hash_init2(&hash_columns,4,system_charset_info, + 0,0,0, (my_hash_get_key) get_key_column,0,0); if (cols) { uint key_prefix_len; @@ -2399,7 +2400,7 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) GRANT_TABLE::~GRANT_TABLE() { - hash_free(&hash_columns); + my_hash_free(&hash_columns); } @@ -2413,7 +2414,7 @@ static uchar* get_grant_table(GRANT_NAME *buff, size_t *length, void free_grant_table(GRANT_TABLE *grant_table) { - hash_free(&grant_table->hash_columns); + my_hash_free(&grant_table->hash_columns); } @@ -2431,11 +2432,11 @@ static GRANT_NAME *name_hash_search(HASH *name_hash, HASH_SEARCH_STATE state; len = (uint) (strmov(strmov(strmov(helping,user)+1,db)+1,tname)-helping)+ 1; - for (grant_name= (GRANT_NAME*) hash_first(name_hash, (uchar*) helping, - len, &state); + for (grant_name= (GRANT_NAME*) my_hash_first(name_hash, (uchar*) helping, + len, &state); grant_name ; - grant_name= (GRANT_NAME*) hash_next(name_hash,(uchar*) helping, - len, &state)) + grant_name= (GRANT_NAME*) my_hash_next(name_hash,(uchar*) helping, + len, &state)) { if (exact) { @@ -2479,7 +2480,8 @@ table_hash_search(const char *host, const char *ip, const char *db, inline GRANT_COLUMN * column_hash_search(GRANT_TABLE *t, const char *cname, uint length) { - return (GRANT_COLUMN*) hash_search(&t->hash_columns, (uchar*) cname,length); + return (GRANT_COLUMN*) my_hash_search(&t->hash_columns, + (uchar*) cname, length); } @@ -2659,7 +2661,7 @@ static int replace_column_table(GRANT_TABLE *g_t, goto end; /* purecov: deadcode */ } if (grant_column) - hash_delete(&g_t->hash_columns,(uchar*) grant_column); + my_hash_delete(&g_t->hash_columns,(uchar*) grant_column); } } } while (!table->file->index_next(table->record[0]) && @@ -2785,7 +2787,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, } else { - hash_delete(&column_priv_hash,(uchar*) grant_table); + my_hash_delete(&column_priv_hash,(uchar*) grant_table); } DBUG_RETURN(0); @@ -2906,7 +2908,8 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name, } else { - hash_delete(is_proc ? &proc_priv_hash : &func_priv_hash,(uchar*) grant_name); + my_hash_delete(is_proc ? &proc_priv_hash : &func_priv_hash,(uchar*) + grant_name); } DBUG_RETURN(0); @@ -3147,8 +3150,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, column_priv= 0; for (uint idx=0 ; idx < grant_table->hash_columns.records ; idx++) { - grant_column= (GRANT_COLUMN*) hash_element(&grant_table->hash_columns, - idx); + grant_column= (GRANT_COLUMN*) + my_hash_element(&grant_table->hash_columns, idx); grant_column->rights&= ~rights; // Fix other columns column_priv|= grant_column->rights; } @@ -3479,9 +3482,9 @@ bool mysql_grant(THD *thd, const char *db, List &list, void grant_free(void) { DBUG_ENTER("grant_free"); - hash_free(&column_priv_hash); - hash_free(&proc_priv_hash); - hash_free(&func_priv_hash); + my_hash_free(&column_priv_hash); + my_hash_free(&proc_priv_hash); + my_hash_free(&func_priv_hash); free_root(&memex,MYF(0)); DBUG_VOID_RETURN; } @@ -3538,12 +3541,12 @@ static my_bool grant_load_procs_priv(TABLE *p_table) MEM_ROOT **save_mem_root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**, THR_MALLOC); DBUG_ENTER("grant_load_procs_priv"); - (void) hash_init(&proc_priv_hash,system_charset_info, - 0,0,0, (hash_get_key) get_grant_table, - 0,0); - (void) hash_init(&func_priv_hash,system_charset_info, - 0,0,0, (hash_get_key) get_grant_table, - 0,0); + (void) my_hash_init(&proc_priv_hash,system_charset_info, + 0,0,0, (my_hash_get_key) get_grant_table, + 0,0); + (void) my_hash_init(&func_priv_hash,system_charset_info, + 0,0,0, (my_hash_get_key) get_grant_table, + 0,0); p_table->file->ha_index_init(0, 1); p_table->use_all_columns(); @@ -3639,9 +3642,9 @@ static my_bool grant_load(THD *thd, TABLE_LIST *tables) thd->variables.sql_mode&= ~MODE_PAD_CHAR_TO_FULL_LENGTH; - (void) hash_init(&column_priv_hash,system_charset_info, - 0,0,0, (hash_get_key) get_grant_table, - (hash_free_key) free_grant_table,0); + (void) my_hash_init(&column_priv_hash,system_charset_info, + 0,0,0, (my_hash_get_key) get_grant_table, + (my_hash_free_key) free_grant_table,0); t_table = tables[0].table; c_table = tables[1].table; @@ -3744,8 +3747,8 @@ static my_bool grant_reload_procs_priv(THD *thd) } else { - hash_free(&old_proc_priv_hash); - hash_free(&old_func_priv_hash); + my_hash_free(&old_proc_priv_hash); + my_hash_free(&old_func_priv_hash); } rw_unlock(&LOCK_grant); @@ -3814,7 +3817,7 @@ my_bool grant_reload(THD *thd) } else { - hash_free(&old_column_priv_hash); + my_hash_free(&old_column_priv_hash); free_root(&old_mem,MYF(0)); } rw_unlock(&LOCK_grant); @@ -4210,7 +4213,7 @@ static bool check_grant_db_routine(THD *thd, const char *db, HASH *hash) for (uint idx= 0; idx < hash->records; ++idx) { - GRANT_NAME *item= (GRANT_NAME*) hash_element(hash, idx); + GRANT_NAME *item= (GRANT_NAME*) my_hash_element(hash, idx); if (strcmp(item->user, sctx->priv_user) == 0 && strcmp(item->db, db) == 0 && @@ -4243,8 +4246,9 @@ bool check_grant_db(THD *thd,const char *db) for (uint idx=0 ; idx < column_priv_hash.records ; idx++) { - GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash, - idx); + GRANT_TABLE *grant_table= (GRANT_TABLE*) + my_hash_element(&column_priv_hash, + idx); if (len < grant_table->key_length && !memcmp(grant_table->hash_key,helping,len) && compare_hostname(&grant_table->host, sctx->host, sctx->ip)) @@ -4716,8 +4720,8 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) for (index=0 ; index < column_priv_hash.records ; index++) { const char *user, *host; - GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash, - index); + GRANT_TABLE *grant_table= (GRANT_TABLE*) + my_hash_element(&column_priv_hash, index); if (!(user=grant_table->user)) user= ""; @@ -4770,7 +4774,7 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) col_index++) { GRANT_COLUMN *grant_column = (GRANT_COLUMN*) - hash_element(&grant_table->hash_columns,col_index); + my_hash_element(&grant_table->hash_columns,col_index); if (grant_column->rights & j) { if (!found_col) @@ -4860,7 +4864,7 @@ static int show_routine_grants(THD* thd, LEX_USER *lex_user, HASH *hash, for (index=0 ; index < hash->records ; index++) { const char *user, *host; - GRANT_NAME *grant_proc= (GRANT_NAME*) hash_element(hash, index); + GRANT_NAME *grant_proc= (GRANT_NAME*) my_hash_element(hash, index); if (!(user=grant_proc->user)) user= ""; @@ -5373,13 +5377,13 @@ static int handle_grant_struct(uint struct_no, bool drop, break; case 2: - grant_name= (GRANT_NAME*) hash_element(&column_priv_hash, idx); + grant_name= (GRANT_NAME*) my_hash_element(&column_priv_hash, idx); user= grant_name->user; host= grant_name->host.hostname; break; case 3: - grant_name= (GRANT_NAME*) hash_element(&proc_priv_hash, idx); + grant_name= (GRANT_NAME*) my_hash_element(&proc_priv_hash, idx); user= grant_name->user; host= grant_name->host.hostname; break; @@ -5412,11 +5416,11 @@ static int handle_grant_struct(uint struct_no, bool drop, break; case 2: - hash_delete(&column_priv_hash, (uchar*) grant_name); + my_hash_delete(&column_priv_hash, (uchar*) grant_name); break; case 3: - hash_delete(&proc_priv_hash, (uchar*) grant_name); + my_hash_delete(&proc_priv_hash, (uchar*) grant_name); break; } elements--; @@ -5930,8 +5934,8 @@ bool mysql_revoke_all(THD *thd, List &list) for (counter= 0, revoked= 0 ; counter < column_priv_hash.records ; ) { const char *user,*host; - GRANT_TABLE *grant_table= (GRANT_TABLE*)hash_element(&column_priv_hash, - counter); + GRANT_TABLE *grant_table= + (GRANT_TABLE*) my_hash_element(&column_priv_hash, counter); if (!(user=grant_table->user)) user= ""; if (!(host=grant_table->host.hostname)) @@ -5977,7 +5981,7 @@ bool mysql_revoke_all(THD *thd, List &list) for (counter= 0, revoked= 0 ; counter < hash->records ; ) { const char *user,*host; - GRANT_NAME *grant_proc= (GRANT_NAME*) hash_element(hash, counter); + GRANT_NAME *grant_proc= (GRANT_NAME*) my_hash_element(hash, counter); if (!(user=grant_proc->user)) user= ""; if (!(host=grant_proc->host.hostname)) @@ -6125,7 +6129,7 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, { for (counter= 0, revoked= 0 ; counter < hash->records ; ) { - GRANT_NAME *grant_proc= (GRANT_NAME*) hash_element(hash, counter); + GRANT_NAME *grant_proc= (GRANT_NAME*) my_hash_element(hash, counter); if (!my_strcasecmp(system_charset_info, grant_proc->db, sp_db) && !my_strcasecmp(system_charset_info, grant_proc->tname, sp_name)) { @@ -6515,7 +6519,7 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond) for (index=0 ; index < column_priv_hash.records ; index++) { const char *user, *host, *is_grantable= "YES"; - GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash, + GRANT_TABLE *grant_table= (GRANT_TABLE*) my_hash_element(&column_priv_hash, index); if (!(user=grant_table->user)) user= ""; @@ -6598,7 +6602,7 @@ int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond) for (index=0 ; index < column_priv_hash.records ; index++) { const char *user, *host, *is_grantable= "YES"; - GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash, + GRANT_TABLE *grant_table= (GRANT_TABLE*) my_hash_element(&column_priv_hash, index); if (!(user=grant_table->user)) user= ""; @@ -6633,7 +6637,7 @@ int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond) col_index++) { GRANT_COLUMN *grant_column = (GRANT_COLUMN*) - hash_element(&grant_table->hash_columns,col_index); + my_hash_element(&grant_table->hash_columns,col_index); if ((grant_column->rights & j) && (table_access & j)) { if (update_schema_privilege(thd, table, buff, grant_table->db, -- cgit v1.2.1 From 0659b857e7fe232ebfe7f48c5e0affd59dbf5862 Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Mon, 19 Oct 2009 14:58:13 +0200 Subject: Bug#27145 EXTRA_ACL troubles The flag EXTRA_ACL is used in conjugation with our access checks, yet it is not clear what impact this flag has. This is a code clean up which replaces use of EXTRA_ACL with an explicit function parameter. The patch also fixes privilege checks for: - SHOW CREATE TABLE: The new privilege requirement is any privilege on the table-level. - CHECKSUM TABLE: Requires SELECT on the table level. - SHOW CREATE VIEW: Requires SHOW_VIEW and SELECT on the table level (just as the manual claims) - SHOW INDEX: Requires any privilege on any column combination. mysql-test/r/grant.result: * Error message now shows correct command (SHOW instead of SELECT) mysql-test/r/grant2.result: * Error message now shows correct command (SHOW instead of SELECT) mysql-test/r/grant4.result: * This test file tests privilege requirements for SHOW COLUMNS CREATE TABLE .. LIKE SHOW CREATE TABLE SHOW INDEX CHECKSUM TABLE SHOW CREATE VIEW mysql-test/r/information_schema_db.result: * Added SELECT privilege to testdb_2 as SHOW CREATE VIEW now demands this privilege as well as SHOW VIEW. mysql-test/r/outfile.result: * Changed error code mysql-test/r/view_grant.result: * Additional SELECT privilege is now needed for SHOW CREATE VIEW mysql-test/t/grant4.test: * This test file tests privilege requirements for SHOW COLUMNS CREATE TABLE .. LIKE SHOW CREATE TABLE SHOW INDEX CHECKSUM TABLE SHOW CREATE VIEW mysql-test/t/information_schema_db.test: * Added SELECT privilege to testdb_2 as SHOW CREATE VIEW now demands this privilege as well as SHOW VIEW. mysql-test/t/outfile.test: * Changed error code mysql-test/t/view_grant.test: * Additional SELECT privilege is now needed for SHOW CREATE VIEW sql/mysql_priv.h: * Replaced EXTRA_ACL with a parameter sql/sp_head.cc: * Replaced EXTRA_ACL with a parameter sql/sql_acl.cc: * Converted function documentation to doxygen and clarified some behaviors. * Changed value from uint to bool to better reflect its meaning. * Removed pointless variable orig_want_access * Added function has_any_table_level_privileges to help with requirements checks during SHOW CREATE TABLE. sql/sql_acl.h: * changed signature of check_grant() * introduced access control function has_any_table_leevl_privileges() sql/sql_base.cc: * Check_table_access has new signature sql/sql_cache.cc: * Check_table_access has new signature sql/sql_parse.cc: * Rewrote function documentation in doxygen comments for: check_access, check_table_acces, check_grant. * Removed EXTRA_ACL flag where it doesn't hold any meaningful purpose anymore and replaced it with a function parameter where any privileges on any column combination would satisfy the requirement. * Fixed privilege check for SHOW COLUMNS and SHOW INDEX * Modified check_table_access to gain clarity in what EXTRA_ACL actually does. * Modified check_access to gain clarity in what EXTRA_ACL actually does. * Fixed privilege check for CREATE TABLE .. LIKE .. ; It now requires SELECT privileges on the table. * Fixed privilege check for SHOW CREATE TABLE ..; It now requires any privilege on the table level. sql/sql_plugin.cc: * check_table_access has new signature sql/sql_prepare.cc: * check_table_access has new signature sql/sql_show.cc: * check_table_access has new signature sql/sql_trigger.cc: * check_table_access has new signature sql/sql_update.cc: * check grant has new signature sql/sql_view.cc: * check_table_access has new signature --- sql/sql_acl.cc | 165 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 137 insertions(+), 28 deletions(-) (limited to 'sql/sql_acl.cc') diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 9ab13438926..a82efbd9f34 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1879,7 +1879,7 @@ static bool test_if_create_new_users(THD *thd) sctx->priv_user, tl.db, 0); if (!(db_access & INSERT_ACL)) { - if (check_grant(thd, INSERT_ACL, &tl, 0, UINT_MAX, 1)) + if (check_grant(thd, INSERT_ACL, &tl, FALSE, UINT_MAX, TRUE)) create_new_users=0; } } @@ -3835,40 +3835,52 @@ end: DBUG_RETURN(return_val); } -/**************************************************************************** - Check table level grants - SYNOPSIS - bool check_grant() - thd Thread handler - want_access Bits of privileges user needs to have - tables List of tables to check. The user should have 'want_access' - to all tables in list. - show_table <> 0 if we are in show table. In this case it's enough to have - any privilege for the table - number Check at most this number of tables. - no_errors If 0 then we write an error. The error is sent directly to - the client +/** + @brief Check table level grants - RETURN - 0 ok - 1 Error: User did not have the requested privileges + @param thd Thread handler + @param want_access Bits of privileges user needs to have. + @param tables List of tables to check. The user should have + 'want_access' to all tables in list. + @param any_combination_will_do TRUE if it's enough to have any privilege for + any combination of the table columns. + @param number Check at most this number of tables. + @param no_errors TRUE if no error should be sent directly to the client. - NOTE - This functions assumes that either number of tables to be inspected + If table->grant.want_privilege != 0 then the requested privileges where + in the set of COL_ACLS but access was not granted on the table level. As + a consequence an extra check of column privileges is required. + + Specifically if this function returns FALSE the user has some kind of + privilege on a combination of columns in each table. + + This function is usually preceeded by check_access which establish the + User-, Db- and Host access rights. + + @see check_access + @see check_table_access + + @note This functions assumes that either number of tables to be inspected by it is limited explicitly (i.e. is is not UINT_MAX) or table list used and thd->lex->query_tables_own_last value correspond to each other (the latter should be either 0 or point to next_global member of one of elements of this table list). -****************************************************************************/ + + @return Access status + @retval FALSE Access granted; But column privileges might need to be + checked. + @retval TRUE The user did not have the requested privileges on any of the + tables. + +*/ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, - uint show_table, uint number, bool no_errors) + bool any_combination_will_do, uint number, bool no_errors) { TABLE_LIST *table, *first_not_own_table= thd->lex->first_not_own_table(); Security_context *sctx= thd->security_ctx; uint i; - ulong orig_want_access= want_access; DBUG_ENTER("check_grant"); DBUG_ASSERT(number > 0); @@ -3886,7 +3898,10 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, i < number && table != first_not_own_table; table= table->next_global, i++) { - /* Remove SHOW_VIEW_ACL, because it will be checked during making view */ + /* + Save a copy of the privileges without the SHOW_VIEW_ACL attribute. + It will be checked during making view. + */ table->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL); } @@ -3899,7 +3914,6 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, sctx = test(table->security_ctx) ? table->security_ctx : thd->security_ctx; - want_access= orig_want_access; want_access&= ~sctx->master_access; if (!want_access) continue; // ok @@ -3929,8 +3943,13 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, want_access &= ~table->grant.privilege; goto err; // No grants } - if (show_table) - continue; // We have some priv on this + + /* + For SHOW COLUMNS, SHOW INDEX it is enough to have some + privileges on any column combination on the table. + */ + if (any_combination_will_do) + continue; table->grant.grant_table=grant_table; // Remember for column test table->grant.version=grant_version; @@ -3948,7 +3967,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, } } rw_unlock(&LOCK_grant); - DBUG_RETURN(0); + DBUG_RETURN(FALSE); err: rw_unlock(&LOCK_grant); @@ -3962,7 +3981,97 @@ err: sctx->host_or_ip, table ? table->get_table_name() : "unknown"); } - DBUG_RETURN(1); + DBUG_RETURN(TRUE); +} + + +/** + Check if all tables in the table list has any of the requested table level + privileges matching the current user. + + @param thd A pointer to the thread context. + @param required_access Set of privileges to compare against. + @param tables[in,out] A list of tables to be checked. + + @note If the table grant hash contains any grant table, this table will be + attached to the corresponding TABLE_LIST object in 'tables'. + + @return + @retval TRUE There is a privilege on the table level granted to the + current user. + @retval FALSE There are no privileges on the table level granted to the + current user. +*/ + +bool has_any_table_level_privileges(THD *thd, ulong required_access, + TABLE_LIST *tables) +{ + + Security_context *sctx; + GRANT_TABLE *grant_table; + TABLE_LIST *table; + + /* For each table in tables */ + for (table= tables; table; table= table->next_global) + { + /* + If this table is a VIEW, then it will supply its own security context. + This is because VIEWs can have a DEFINER or an INVOKER security role. + */ + sctx= table->security_ctx ? table->security_ctx : thd->security_ctx; + + /* + Get privileges from table_priv and column_priv tables by searching + the cache. + */ + rw_rdlock(&LOCK_grant); + grant_table= table_hash_search(sctx->host, sctx->ip, + table->db, sctx->priv_user, + table->table_name,0); + rw_unlock(&LOCK_grant); + + /* Stop if there are no grants for the current user */ + if (!grant_table) + return FALSE; + + /* + Save a pointer to the found grant_table in the table object. + This pointer can later be used to verify other access requirements + without having to look up the grant table in the hash. + */ + table->grant.grant_table= grant_table; + table->grant.version= grant_version; + table->grant.privilege|= grant_table->privs; + /* + Save all privileges which might be subject to column privileges + but not which aren't yet granted by table level ACLs. + This is can later be used for column privilege checks. + */ + table->grant.want_privilege= ((required_access & COL_ACLS) + & ~table->grant.privilege); + + /* + If the requested privileges share any intersection with the current + table privileges we have found at least one common privilege on the + table level. + */ + if (grant_table->privs & required_access) + continue; /* Check next table */ + + /* + There are no table level privileges which satisfies any of the + requested privileges. There might still be column privileges which + does though. + */ + return FALSE; + } + + /* + All tables in TABLE_LIST satisfy the requirement of having any + privilege on the table level. + */ + + return TRUE; } -- cgit v1.2.1 From 8ec23470f14323bb85220bae42d154681a4be7f3 Mon Sep 17 00:00:00 2001 From: Konstantin Osipov Date: Thu, 22 Oct 2009 00:02:06 +0400 Subject: Backport of revno 2630.28.10, 2630.28.31, 2630.28.26, 2630.33.1, 2630.39.1, 2630.28.29, 2630.34.3, 2630.34.2, 2630.34.1, 2630.29.29, 2630.29.28, 2630.31.1, 2630.28.13, 2630.28.10, 2617.23.14 and some other minor revisions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch implements: WL#4264 "Backup: Stabilize Service Interface" -- all the server prerequisites except si_objects.{h,cc} themselves (they can be just copied over, when needed). WL#4435: Support OUT-parameters in prepared statements. (and all issues in the initial patches for these two tasks, that were discovered in pushbuild and during testing). Bug#39519: mysql_stmt_close() should flush all data associated with the statement. After execution of a prepared statement, send OUT parameters of the invoked stored procedure, if any, to the client. When using the binary protocol, send the parameters in an additional result set over the wire. When using the text protocol, assign out parameters to the user variables from the CALL(@var1, @var2, ...) specification. The following refactoring has been made: - Protocol::send_fields() was renamed to Protocol::send_result_set_metadata(); - A new Protocol::send_result_set_row() was introduced to incapsulate common functionality for sending row data. - Signature of Protocol::prepare_for_send() was changed: this operation does not need a list of items, the number of items is fully sufficient. The following backward incompatible changes have been made: - CLIENT_MULTI_RESULTS is now enabled by default in the client; - CLIENT_PS_MULTI_RESUTLS is now enabled by default in the client. include/mysql.h: Add a new flag to MYSQL_METHODS::flush_use_result function pointer. This flag determines if all results should be flushed or only the first one: - if flush_all_results is TRUE, then cli_flush_use_result() will read/flush all pending results. I.e. it will read all packets while server status attribute indicates that there are more results. This is a new semantic, required to fix the bug. - if flush_all_results is FALSE, the old sematic is preserved -- i.e. cli_flush_use_result() reads data until first EOF-packet. include/mysql.h.pp: Update the ABI with new calls (compatible changes). include/mysql_com.h: Add CLIENT_PS_OUT_PARAMS -- a client capability indicating that the client supportsю libmysql/libmysql.c: Add mysql_stmt_next_result() -- analogue of mysql_next_result() for binary protocol. Fix a minor bug in alloc_fields() -- not all members were copied over, and some only shallow-copied (catalog). Flush all results in mysql_stmt_close() (Bug#39519). libmysqld/lib_sql.cc: Rename send_fields() -> send_result_set_metadata(). Refactoring: change prepare_for_send() so that it accepts only what it really needs -- a number of elements in the list. mysql-test/r/ps.result: Update results: WL#4435. mysql-test/t/ps.test: WL#4435: A test case for an SQL-part of the problem. sql-common/client.c: Bug#39519. Implement new functionality in cli_flush_use_result(): if flush_all_delete is TRUE, then it should read/flush all pending results. sql/Makefile.am: Add a new header sql_prepare.h to the list of build headers. sql/events.cc: Rename: Protocol::send_fields() -> Protocol::send_result_set_metadata(). sql/handler.cc: Rename: Protocol::send_fields() -> Protocol::send_result_set_metadata(). sql/mysql_priv.h: Move sql_prepare.cc-specific declarations to a new header - sql_prepare.h. sql/procedure.h: Rename: Protocol::send_fields() -> Protocol::send_result_set_metadata(). sql/protocol.cc: Move the logic responsible for sending of one result set row to the Protocol class. Define a template for end-of-statement action. Refactoring: change prepare_for_send() so that it accepts only what it really needs -- a number of elements in the list. Rename send_fields() to send_result_set_metadata(). sql/protocol.h: Update with new declarations (WL#4435). Rename send_fields() -> send_result_set_metadata(). prepare_for_send() only needs the number of columns to send, and doesn't use the item list - update signature to require only what's needed. Add a new protocol type -- Protocol_local. sql/repl_failsafe.cc: Rename: Protocol::send_fields() -> Protocol::send_result_set_metadata(). sql/slave.cc: Rename: Protocol::send_fields() -> Protocol::send_result_set_metadata(). sql/sql_acl.cc: Rename: Protocol::send_fields() -> Protocol::send_result_set_metadata(). sql/sql_base.cc: Include sql_prepare.h (for Reprepare_observer). sql/sql_cache.cc: Extend the query cache flags block to be able to store a numeric id for the result format, not just a flag binary/non-binary. sql/sql_class.cc: Update to use the rename of Protocol::send_fields() to Protocol::send_result_set_metadata(). Use Protocol::send_one_result_set_row(). sql/sql_class.h: Move the declaration of Reprepare_observer to the new header - sql_prepare.h. Update to the new signature of class Protocol::send_fields(). sql/sql_connect.cc: Use a protocol template method instead of raw NET layer API at the end of a statement. sql/sql_cursor.cc: Rename: Protocol::send_fields() -> Protocol::send_result_set_metadata(). sql/sql_error.cc: Rename: Protocol::send_fields() -> Protocol::send_result_set_metadata(). sql/sql_handler.cc: Rename: Protocol::send_fields() -> Protocol::send_result_set_metadata(). Use new method Protocol::send_one_result_set_row(). sql/sql_help.cc: Rename: Protocol::send_fields() -> Protocol::send_result_set_metadata(). sql/sql_lex.cc: Initialize multi_statements variable. Add a handy constant for empty lex string. sql/sql_lex.h: Add a separate member for a standalone parsing option - multi-statements support. sql/sql_list.cc: sql_list.h is a standalone header now, no need to include mysql_priv.h. sql/sql_list.h: Make sql_list.h a stand-alone header. sql/sql_parse.cc: Include sql_prepare.h for prepared statements- related declarations. Use a new Protocol template method to end each statement (send OK, EOF or ERROR to the client). sql/sql_prepare.cc: Implement Execute Direct API (WL#4264), currently unused. It will be used by the service interface (Backup). Use a new header - sql_prepare.h. Add support for OUT parameters in the binary and text protocol (prepared statements only). sql/sql_prepare.h: Add a new header to contain (for now) all prepared statement- external related declarations. sql/sql_profile.cc: Rename: Protocol::send_fields() -> Protocol::send_result_set_metadata(). sql/sql_repl.cc: Rename: Protocol::send_fields() -> Protocol::send_result_set_metadata(). sql/sql_select.cc: Rename: Protocol::send_fields() -> Protocol::send_result_set_metadata(). sql/sql_show.cc: Rename: Protocol::send_fields() -> Protocol::send_result_set_metadata(). sql/sql_string.h: Add a way to convert a String to LEX_STRING. sql/sql_table.cc: Rename: Protocol::send_fields() -> Protocol::send_result_set_metadata(). sql/sql_update.cc: Remove an extraneous my_error(). The error is already reported in update_non_unique_table_error(). sql/sql_yacc.yy: Support for multi-statements is an independent property of parsing, not derived from the protocol type. tests/mysql_client_test.c: Add tests for WL#4435 (binary protocol). --- sql/sql_acl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql/sql_acl.cc') diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 040c985560e..d3fb8e3fe5c 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -4532,7 +4532,7 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) strxmov(buff,"Grants for ",lex_user->user.str,"@", lex_user->host.str,NullS); field_list.push_back(field); - if (protocol->send_fields(&field_list, + if (protocol->send_result_set_metadata(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) { VOID(pthread_mutex_unlock(&acl_cache->lock)); -- cgit v1.2.1 From 795102b786910f6b5eaeb16fc75a9c02867fb07b Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Fri, 23 Oct 2009 16:02:20 +0500 Subject: Bug#35427 INFORMATION_SCHEMA.TABLES.TABLE_CATALOG is NULL, should be "def" backport to betony --- sql/sql_acl.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'sql/sql_acl.cc') diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index dcda3c038ce..da2232d1478 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -6334,6 +6334,7 @@ static bool update_schema_privilege(THD *thd, TABLE *table, char *buff, CHARSET_INFO *cs= system_charset_info; restore_record(table, s->default_values); table->field[0]->store(buff, (uint) strlen(buff), cs); + table->field[1]->store(STRING_WITH_LEN("def"), cs); if (db) table->field[i++]->store(db, (uint) strlen(db), cs); if (t_name) -- cgit v1.2.1