diff options
-rw-r--r-- | BitKeeper/etc/logging_ok | 1 | ||||
-rw-r--r-- | mysql-test/r/sp-security.result | 49 | ||||
-rw-r--r-- | mysql-test/t/sp-security.test | 73 | ||||
-rw-r--r-- | sql/sp_head.cc | 3 | ||||
-rw-r--r-- | sql/sql_acl.cc | 22 | ||||
-rw-r--r-- | sql/sql_parse.cc | 4 |
6 files changed, 137 insertions, 15 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 6e53347b0a6..b8607af3b3c 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -24,6 +24,7 @@ bk@admin.bk bk@mysql.r18.ru carsten@tsort.bitbybit.dk davida@isil.mysql.com +dlenev@brandersnatch.localdomain dlenev@build.mysql.com dlenev@mysql.com gerberb@ou800.zenez.com diff --git a/mysql-test/r/sp-security.result b/mysql-test/r/sp-security.result index 9d5f71225b6..c4fbece9d72 100644 --- a/mysql-test/r/sp-security.result +++ b/mysql-test/r/sp-security.result @@ -1,5 +1,6 @@ use test; -grant usage on *.* to dummy@localhost; +grant usage on *.* to user1@localhost; +flush privileges; drop database if exists db1_secret; create database db1_secret; use db1_secret; @@ -15,14 +16,14 @@ u i root@localhost 1 call stamp(2); select * from db1_secret.t1; -ERROR 42000: Access denied for user: 'dummy'@'localhost' to database 'db1_secret' +ERROR 42000: Access denied for user: 'user1'@'localhost' to database 'db1_secret' call stamp(3); select * from db1_secret.t1; ERROR 42000: Access denied for user: ''@'localhost' to database 'db1_secret' select * from t1; u i root@localhost 1 -dummy@localhost 2 +user1@localhost 2 anon@localhost 3 alter procedure stamp sql security invoker; show procedure status like 'stamp'; @@ -32,14 +33,50 @@ call stamp(4); select * from t1; u i root@localhost 1 -dummy@localhost 2 +user1@localhost 2 anon@localhost 3 root@localhost 4 call stamp(5); -ERROR 42000: Access denied for user: 'dummy'@'localhost' to database 'db1_secret' +ERROR 42000: Access denied for user: 'user1'@'localhost' to database 'db1_secret' call stamp(6); ERROR 42000: Access denied for user: ''@'localhost' to database 'db1_secret' +drop database if exists db2; +create database db2; +use db2; +create table t2 (s1 int); +insert into t2 values (0); +grant usage on db2.* to user1@localhost; +grant select on db2.* to user1@localhost; +grant usage on db2.* to user2@localhost; +grant select,insert,update,delete on db2.* to user2@localhost; +flush privileges; +use db2; +create procedure p () insert into t2 values (1); +call p(); +ERROR 42000: Access denied for user: 'user1'@'localhost' to database 'db2' +use db2; +call p(); +ERROR 42000: Access denied for user: 'user1'@'localhost' to database 'db2' +select * from t2; +s1 +0 +create procedure q () insert into t2 values (2); +call q(); +select * from t2; +s1 +0 +2 +use db2; +call q(); +select * from t2; +s1 +0 +2 +2 drop procedure stamp; +drop procedure p; +drop procedure q; use test; drop database db1_secret; -delete from mysql.user where user='dummy'; +drop database db2; +delete from mysql.user where user='user1' or user='user2'; diff --git a/mysql-test/t/sp-security.test b/mysql-test/t/sp-security.test index 0d77b53210e..ac7477869a1 100644 --- a/mysql-test/t/sp-security.test +++ b/mysql-test/t/sp-security.test @@ -7,8 +7,9 @@ connect (con1root,localhost,root,,); connection con1root; use test; -# Create dummy user with no particular access rights -grant usage on *.* to dummy@localhost; +# Create user user1 with no particular access rights +grant usage on *.* to user1@localhost; +flush privileges; --disable_warnings drop database if exists db1_secret; @@ -30,13 +31,13 @@ show procedure status like 'stamp'; call stamp(1); select * from t1; -connect (con2dummy,localhost,dummy,,); +connect (con2user1,localhost,user1,,); connect (con3anon,localhost,anon,,); # -# Dummy can +# User1 can # -connection con2dummy; +connection con2user1; # This should work... call stamp(2); @@ -75,9 +76,9 @@ call stamp(4); select * from t1; # -# Dummy cannot +# User1 cannot # -connection con2dummy; +connection con2user1; # This should not work --error 1044 @@ -92,9 +93,65 @@ connection con3anon; --error 1044 call stamp(6); + +# +# BUG#2777 +# + +connection con1root; +--disable_warnings +drop database if exists db2; +--enable_warnings +create database db2; + +use db2; + +create table t2 (s1 int); +insert into t2 values (0); + +grant usage on db2.* to user1@localhost; +grant select on db2.* to user1@localhost; +grant usage on db2.* to user2@localhost; +grant select,insert,update,delete on db2.* to user2@localhost; +flush privileges; + +connection con2user1; +use db2; + +create procedure p () insert into t2 values (1); + +# Check that this doesn't work. +--error 1044 +call p(); + +connect (con4user2,localhost,user2,,); + +connection con4user2; +use db2; + +# This should not work, since p is executed with definer's (user1's) rights. +--error 1044 +call p(); +select * from t2; + +create procedure q () insert into t2 values (2); + +call q(); +select * from t2; + +connection con2user1; +use db2; + +# This should work +call q(); +select * from t2; + # Clean up connection con1root; drop procedure stamp; +drop procedure p; +drop procedure q; use test; drop database db1_secret; -delete from mysql.user where user='dummy'; +drop database db2; +delete from mysql.user where user='user1' or user='user2'; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index d43ac54e57d..eebe02c1834 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -842,7 +842,10 @@ sp_instr_stmt::exec_stmt(THD *thd, LEX *lex) thd->lex->unit.thd= thd; // QQ Not reentrant freelist= thd->free_list; thd->free_list= NULL; + + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query_id= query_id++; + VOID(pthread_mutex_unlock(&LOCK_thread_count)); // Copy WHERE clause pointers to avoid damaging by optimisation // Also clear ref_pointer_arrays. diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 5febb49e110..d294055ff8a 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -794,6 +794,7 @@ int acl_getroot_no_password(THD *thd) { ulong user_access= NO_ACCESS; int res= 1; + uint i; ACL_USER *acl_user= 0; DBUG_ENTER("acl_getroot_no_password"); @@ -810,13 +811,16 @@ int acl_getroot_no_password(THD *thd) VOID(pthread_mutex_lock(&acl_cache->lock)); + thd->master_access= 0; + thd->db_access= 0; + /* Find acl entry in user database. This is specially tailored to suit the check we do for CALL of a stored procedure; thd->user is set to what is actually a priv_user, which can be ''. */ - for (uint i=0 ; i < acl_users.elements ; i++) + for (i=0 ; i < acl_users.elements ; i++) { acl_user= dynamic_element(&acl_users,i,ACL_USER*); if ((!acl_user->user && (!thd->user || !thd->user[0])) || @@ -832,6 +836,22 @@ int acl_getroot_no_password(THD *thd) if (acl_user) { + for (i=0 ; i < acl_dbs.elements ; i++) + { + ACL_DB *acl_db= dynamic_element(&acl_dbs, i, ACL_DB*); + if (!acl_db->user || + (thd->user && thd->user[0] && !strcmp(thd->user, acl_db->user))) + { + if (compare_hostname(&acl_db->host, thd->host, thd->ip)) + { + if (!acl_db->db || (thd->db && !strcmp(acl_db->db, thd->db))) + { + thd->db_access= acl_db->access; + break; + } + } + } + } thd->master_access= acl_user->access; thd->priv_user= acl_user->user ? thd->user : (char *) ""; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 9de3247496c..273e994189f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1086,6 +1086,10 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg) thd->query_length=length; thd->query= thd->memdup_w_gap(buff, length+1, thd->db_length+1); thd->query[length] = '\0'; + /* + We don't need to obtain LOCK_thread_count here because in bootstrap + mode we have only one thread. + */ thd->query_id=query_id++; if (mqh_used && thd->user_connect && check_mqh(thd, SQLCOM_END)) { |