Skip to content

Commit 9901efe

Browse files
author
gluh@eagle.intranet.mysql.r18.ru
committed
Bug#15298 SHOW GRANTS FOR CURRENT_USER: Incorrect output in DEFINER context
user name is calculated on function execution stage instead of parse stage
1 parent e5dbc49 commit 9901efe

File tree

6 files changed

+149
-53
lines changed

6 files changed

+149
-53
lines changed

mysql-test/r/sp_notembedded.result

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,17 @@ drop procedure bug10100pd|
206206
drop procedure bug10100pc|
207207
drop view v1|
208208
drop table t3|
209+
drop procedure if exists bug15298_1;
210+
drop procedure if exists bug15298_2;
211+
grant all privileges on test.* to 'mysqltest_1'@'localhost';
212+
create procedure 15298_1 () sql security definer show grants for current_user;
213+
create procedure 15298_2 () sql security definer show grants;
214+
call 15298_1();
215+
Grants for root@localhost
216+
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION
217+
call 15298_2();
218+
Grants for root@localhost
219+
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION
220+
drop user mysqltest_1@localhost;
221+
drop procedure 15298_1;
222+
drop procedure 15298_2;

mysql-test/t/sp_notembedded.test

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,3 +265,23 @@ drop view v1|
265265
drop table t3|
266266

267267
delimiter ;|
268+
269+
#
270+
# Bug#15298 SHOW GRANTS FOR CURRENT_USER: Incorrect output in DEFINER context
271+
#
272+
--disable_warnings
273+
drop procedure if exists bug15298_1;
274+
drop procedure if exists bug15298_2;
275+
--enable_warnings
276+
grant all privileges on test.* to 'mysqltest_1'@'localhost';
277+
create procedure 15298_1 () sql security definer show grants for current_user;
278+
create procedure 15298_2 () sql security definer show grants;
279+
280+
connect (con1,localhost,mysqltest_1,,test);
281+
call 15298_1();
282+
call 15298_2();
283+
284+
connection default;
285+
drop user mysqltest_1@localhost;
286+
drop procedure 15298_1;
287+
drop procedure 15298_2;

sql/mysql_priv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,7 @@ int append_query_string(CHARSET_INFO *csinfo,
537537
void get_default_definer(THD *thd, LEX_USER *definer);
538538
LEX_USER *create_default_definer(THD *thd);
539539
LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name);
540+
LEX_USER *get_current_user(THD *thd, LEX_USER *user);
540541

541542
enum enum_mysql_completiontype {
542543
ROLLBACK_RELEASE=-2, ROLLBACK=1, ROLLBACK_AND_CHAIN=7,

sql/sql_acl.cc

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2766,7 +2766,7 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
27662766
{
27672767
ulong column_priv= 0;
27682768
List_iterator <LEX_USER> str_list (user_list);
2769-
LEX_USER *Str;
2769+
LEX_USER *Str, *tmp_Str;
27702770
TABLE_LIST tables[3];
27712771
bool create_new_users=0;
27722772
char *db_name, *table_name;
@@ -2891,10 +2891,15 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
28912891
thd->mem_root= &memex;
28922892
grant_version++;
28932893

2894-
while ((Str = str_list++))
2894+
while ((tmp_Str = str_list++))
28952895
{
28962896
int error;
28972897
GRANT_TABLE *grant_table;
2898+
if (!(Str= get_current_user(thd, tmp_Str)))
2899+
{
2900+
result= TRUE;
2901+
continue;
2902+
}
28982903
if (Str->host.length > HOSTNAME_LENGTH ||
28992904
Str->user.length > USERNAME_LENGTH)
29002905
{
@@ -3030,7 +3035,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
30303035
bool revoke_grant, bool no_error)
30313036
{
30323037
List_iterator <LEX_USER> str_list (user_list);
3033-
LEX_USER *Str;
3038+
LEX_USER *Str, *tmp_Str;
30343039
TABLE_LIST tables[2];
30353040
bool create_new_users=0, result=0;
30363041
char *db_name, *table_name;
@@ -3098,10 +3103,15 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
30983103

30993104
DBUG_PRINT("info",("now time to iterate and add users"));
31003105

3101-
while ((Str= str_list++))
3106+
while ((tmp_Str= str_list++))
31023107
{
31033108
int error;
31043109
GRANT_NAME *grant_name;
3110+
if (!(Str= get_current_user(thd, tmp_Str)))
3111+
{
3112+
result= TRUE;
3113+
continue;
3114+
}
31053115
if (Str->host.length > HOSTNAME_LENGTH ||
31063116
Str->user.length > USERNAME_LENGTH)
31073117
{
@@ -3170,7 +3180,7 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
31703180
ulong rights, bool revoke_grant)
31713181
{
31723182
List_iterator <LEX_USER> str_list (list);
3173-
LEX_USER *Str;
3183+
LEX_USER *Str, *tmp_Str;
31743184
char tmp_db[NAME_LEN+1];
31753185
bool create_new_users=0;
31763186
TABLE_LIST tables[2];
@@ -3229,8 +3239,13 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
32293239
grant_version++;
32303240

32313241
int result=0;
3232-
while ((Str = str_list++))
3242+
while ((tmp_Str = str_list++))
32333243
{
3244+
if (!(Str= get_current_user(thd, tmp_Str)))
3245+
{
3246+
result= TRUE;
3247+
continue;
3248+
}
32343249
if (Str->host.length > HOSTNAME_LENGTH ||
32353250
Str->user.length > USERNAME_LENGTH)
32363251
{
@@ -5187,7 +5202,7 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list)
51875202
int result;
51885203
String wrong_users;
51895204
ulong sql_mode;
5190-
LEX_USER *user_name;
5205+
LEX_USER *user_name, *tmp_user_name;
51915206
List_iterator <LEX_USER> user_list(list);
51925207
TABLE_LIST tables[GRANT_TABLES];
51935208
DBUG_ENTER("mysql_create_user");
@@ -5199,8 +5214,13 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list)
51995214
rw_wrlock(&LOCK_grant);
52005215
VOID(pthread_mutex_lock(&acl_cache->lock));
52015216

5202-
while ((user_name= user_list++))
5217+
while ((tmp_user_name= user_list++))
52035218
{
5219+
if (!(user_name= get_current_user(thd, tmp_user_name)))
5220+
{
5221+
result= TRUE;
5222+
continue;
5223+
}
52045224
/*
52055225
Search all in-memory structures and grant tables
52065226
for a mention of the new user name.
@@ -5246,7 +5266,7 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list)
52465266
{
52475267
int result;
52485268
String wrong_users;
5249-
LEX_USER *user_name;
5269+
LEX_USER *user_name, *tmp_user_name;
52505270
List_iterator <LEX_USER> user_list(list);
52515271
TABLE_LIST tables[GRANT_TABLES];
52525272
DBUG_ENTER("mysql_drop_user");
@@ -5258,8 +5278,14 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list)
52585278
rw_wrlock(&LOCK_grant);
52595279
VOID(pthread_mutex_lock(&acl_cache->lock));
52605280

5261-
while ((user_name= user_list++))
5281+
while ((tmp_user_name= user_list++))
52625282
{
5283+
user_name= get_current_user(thd, tmp_user_name);
5284+
if (!(user_name= get_current_user(thd, tmp_user_name)))
5285+
{
5286+
result= TRUE;
5287+
continue;
5288+
}
52635289
if (handle_grant_data(tables, 1, user_name, NULL) <= 0)
52645290
{
52655291
append_user(&wrong_users, user_name);
@@ -5296,8 +5322,8 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
52965322
{
52975323
int result;
52985324
String wrong_users;
5299-
LEX_USER *user_from;
5300-
LEX_USER *user_to;
5325+
LEX_USER *user_from, *tmp_user_from;
5326+
LEX_USER *user_to, *tmp_user_to;
53015327
List_iterator <LEX_USER> user_list(list);
53025328
TABLE_LIST tables[GRANT_TABLES];
53035329
DBUG_ENTER("mysql_rename_user");
@@ -5309,9 +5335,19 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
53095335
rw_wrlock(&LOCK_grant);
53105336
VOID(pthread_mutex_lock(&acl_cache->lock));
53115337

5312-
while ((user_from= user_list++))
5338+
while ((tmp_user_from= user_list++))
53135339
{
5314-
user_to= user_list++;
5340+
if (!(user_from= get_current_user(thd, tmp_user_from)))
5341+
{
5342+
result= TRUE;
5343+
continue;
5344+
}
5345+
tmp_user_to= user_list++;
5346+
if (!(user_to= get_current_user(thd, tmp_user_to)))
5347+
{
5348+
result= TRUE;
5349+
continue;
5350+
}
53155351
DBUG_ASSERT(user_to != 0); /* Syntax enforces pairs of users. */
53165352

53175353
/*
@@ -5366,10 +5402,15 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
53665402
rw_wrlock(&LOCK_grant);
53675403
VOID(pthread_mutex_lock(&acl_cache->lock));
53685404

5369-
LEX_USER *lex_user;
5405+
LEX_USER *lex_user, *tmp_lex_user;
53705406
List_iterator <LEX_USER> user_list(list);
5371-
while ((lex_user=user_list++))
5407+
while ((tmp_lex_user= user_list++))
53725408
{
5409+
if (!(lex_user= get_current_user(thd, tmp_lex_user)))
5410+
{
5411+
result= -1;
5412+
continue;
5413+
}
53735414
if (!find_acl_user(lex_user->host.str, lex_user->user.str, TRUE))
53745415
{
53755416
sql_print_error("REVOKE ALL PRIVILEGES, GRANT: User '%s'@'%s' does not "

sql/sql_parse.cc

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3887,11 +3887,13 @@ mysql_execute_command(THD *thd)
38873887

38883888
if (thd->security_ctx->user) // If not replication
38893889
{
3890-
LEX_USER *user;
3890+
LEX_USER *user, *tmp_user;
38913891

38923892
List_iterator <LEX_USER> user_list(lex->users_list);
3893-
while ((user= user_list++))
3893+
while ((tmp_user= user_list++))
38943894
{
3895+
if (!(user= get_current_user(thd, tmp_user)))
3896+
goto error;
38953897
if (specialflag & SPECIAL_NO_RESOLVE &&
38963898
hostname_requires_resolving(user->host.str))
38973899
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
@@ -3973,9 +3975,13 @@ mysql_execute_command(THD *thd)
39733975
if (lex->sql_command == SQLCOM_GRANT)
39743976
{
39753977
List_iterator <LEX_USER> str_list(lex->users_list);
3976-
LEX_USER *user;
3977-
while ((user=str_list++))
3978+
LEX_USER *user, *tmp_user;
3979+
while ((tmp_user=str_list++))
3980+
{
3981+
if (!(user= get_current_user(thd, tmp_user)))
3982+
goto error;
39783983
reset_mqh(user);
3984+
}
39793985
}
39803986
}
39813987
}
@@ -4030,13 +4036,18 @@ mysql_execute_command(THD *thd)
40304036
}
40314037
#ifndef NO_EMBEDDED_ACCESS_CHECKS
40324038
case SQLCOM_SHOW_GRANTS:
4039+
{
4040+
LEX_USER *grant_user= get_current_user(thd, lex->grant_user);
4041+
if (!grant_user)
4042+
goto error;
40334043
if ((thd->security_ctx->priv_user &&
4034-
!strcmp(thd->security_ctx->priv_user, lex->grant_user->user.str)) ||
4044+
!strcmp(thd->security_ctx->priv_user, grant_user->user.str)) ||
40354045
!check_access(thd, SELECT_ACL, "mysql",0,1,0,0))
40364046
{
4037-
res = mysql_show_grants(thd,lex->grant_user);
4047+
res = mysql_show_grants(thd, grant_user);
40384048
}
40394049
break;
4050+
}
40404051
#endif
40414052
case SQLCOM_HA_OPEN:
40424053
DBUG_ASSERT(first_table == all_tables && first_table != 0);
@@ -7495,3 +7506,34 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name)
74957506

74967507
return definer;
74977508
}
7509+
7510+
7511+
/*
7512+
Retuns information about user or current user.
7513+
7514+
SYNOPSIS
7515+
get_current_user()
7516+
thd [in] thread handler
7517+
user [in] user
7518+
7519+
RETURN
7520+
On success, return a valid pointer to initialized
7521+
LEX_USER, which contains user information.
7522+
On error, return 0.
7523+
*/
7524+
7525+
LEX_USER *get_current_user(THD *thd, LEX_USER *user)
7526+
{
7527+
LEX_USER *curr_user;
7528+
if (!user->user.str) // current_user
7529+
{
7530+
if (!(curr_user= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
7531+
{
7532+
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(LEX_USER));
7533+
return 0;
7534+
}
7535+
get_default_definer(thd, curr_user);
7536+
return curr_user;
7537+
}
7538+
return user;
7539+
}

sql/sql_yacc.yy

Lines changed: 9 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6510,24 +6510,10 @@ show_param:
65106510
{
65116511
LEX *lex=Lex;
65126512
lex->sql_command= SQLCOM_SHOW_GRANTS;
6513-
THD *thd= lex->thd;
6514-
Security_context *sctx= thd->security_ctx;
65156513
LEX_USER *curr_user;
6516-
if (!(curr_user= (LEX_USER*) thd->alloc(sizeof(st_lex_user))))
6514+
if (!(curr_user= (LEX_USER*) lex->thd->alloc(sizeof(st_lex_user))))
65176515
YYABORT;
6518-
curr_user->user.str= sctx->priv_user;
6519-
curr_user->user.length= strlen(sctx->priv_user);
6520-
if (*sctx->priv_host != 0)
6521-
{
6522-
curr_user->host.str= sctx->priv_host;
6523-
curr_user->host.length= strlen(sctx->priv_host);
6524-
}
6525-
else
6526-
{
6527-
curr_user->host.str= (char *) "%";
6528-
curr_user->host.length= 1;
6529-
}
6530-
curr_user->password=null_lex_str;
6516+
bzero(curr_user, sizeof(st_lex_user));
65316517
lex->grant_user= curr_user;
65326518
}
65336519
| GRANTS FOR_SYM user
@@ -7477,22 +7463,14 @@ user:
74777463
}
74787464
| CURRENT_USER optional_braces
74797465
{
7480-
THD *thd= YYTHD;
7481-
Security_context *sctx= thd->security_ctx;
7482-
if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
7466+
if (!($$=(LEX_USER*) YYTHD->alloc(sizeof(st_lex_user))))
74837467
YYABORT;
7484-
$$->user.str= sctx->priv_user;
7485-
$$->user.length= strlen(sctx->priv_user);
7486-
if (*sctx->priv_host != 0)
7487-
{
7488-
$$->host.str= sctx->priv_host;
7489-
$$->host.length= strlen(sctx->priv_host);
7490-
}
7491-
else
7492-
{
7493-
$$->host.str= (char *) "%";
7494-
$$->host.length= 1;
7495-
}
7468+
/*
7469+
empty LEX_USER means current_user and
7470+
will be handled in the get_current_user() function
7471+
later
7472+
*/
7473+
bzero($$, sizeof(LEX_USER));
74967474
};
74977475

74987476
/* Keyword that we allow for identifiers (except SP labels) */

0 commit comments

Comments
 (0)