Commit a51ea111 authored by monty@narttu.mysql.fi's avatar monty@narttu.mysql.fi

SHOW GRANTS hided real grants when grants on both column and table (Bug 654)

parent 3bd661a6
drop table if exists t1;
delete from mysql.user where user='mysqltest_1'; delete from mysql.user where user='mysqltest_1';
delete from mysql.db where user='mysqltest_1'; delete from mysql.db where user='mysqltest_1';
flush privileges; flush privileges;
...@@ -64,8 +65,44 @@ GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, CREATE TE ...@@ -64,8 +65,44 @@ GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, CREATE TE
revoke all privileges on mysqltest.* from mysqltest_1@localhost; revoke all privileges on mysqltest.* from mysqltest_1@localhost;
delete from mysql.user where user='mysqltest_1'; delete from mysql.user where user='mysqltest_1';
flush privileges; flush privileges;
grant usage on test.* to user@localhost with grant option; grant usage on test.* to mysqltest_1@localhost with grant option;
show grants for user@localhost; show grants for mysqltest_1@localhost;
Grants for user@localhost Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'user'@'localhost' GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
GRANT USAGE ON `test`.* TO 'user'@'localhost' WITH GRANT OPTION GRANT USAGE ON `mysqltest`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION
GRANT USAGE ON `test`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION
delete from mysql.user where user='mysqltest_1';
delete from mysql.db where user='mysqltest_1';
delete from mysql.tables_priv where user='mysqltest_1';
delete from mysql.columns_priv where user='mysqltest_1';
flush privileges;
create table t1 (a int);
GRANT select,update,insert on t1 to mysqltest_1@localhost;
GRANT select (a), update (a),insert(a), references(a) on t1 to mysqltest_1@localhost;
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
GRANT SELECT, SELECT (a), INSERT, INSERT (a), UPDATE, UPDATE (a), REFERENCES (a) ON `test`.`t1` TO 'mysqltest_1'@'localhost'
select table_priv,column_priv from mysql.tables_priv where user="mysqltest_1";
table_priv column_priv
Select,Insert,Update Select,Insert,Update,References
REVOKE select (a), update on t1 from mysqltest_1@localhost;
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
GRANT SELECT, INSERT, INSERT (a), REFERENCES (a) ON `test`.`t1` TO 'mysqltest_1'@'localhost'
REVOKE insert,insert (a) on t1 from mysqltest_1@localhost;
GRANT references on t1 to mysqltest_1@localhost;
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
GRANT SELECT, REFERENCES, REFERENCES (a) ON `test`.`t1` TO 'mysqltest_1'@'localhost'
select table_priv,column_priv from mysql.tables_priv where user="mysqltest_1";
table_priv column_priv
Select,References References
delete from mysql.user where user='mysqltest_1';
delete from mysql.db where user='mysqltest_1';
delete from mysql.tables_priv where user='mysqltest_1';
delete from mysql.columns_priv where user='mysqltest_1';
flush privileges;
drop table t1;
--disable_warnings
drop table if exists t1;
--enable_warnings
# #
# Test that SSL options works properly # Test that SSL options works properly
# #
...@@ -39,6 +43,32 @@ show grants for mysqltest_1@localhost; ...@@ -39,6 +43,32 @@ show grants for mysqltest_1@localhost;
revoke all privileges on mysqltest.* from mysqltest_1@localhost; revoke all privileges on mysqltest.* from mysqltest_1@localhost;
delete from mysql.user where user='mysqltest_1'; delete from mysql.user where user='mysqltest_1';
flush privileges; flush privileges;
grant usage on test.* to user@localhost with grant option; grant usage on test.* to mysqltest_1@localhost with grant option;
show grants for user@localhost; show grants for mysqltest_1@localhost;
delete from mysql.user where user='mysqltest_1';
delete from mysql.db where user='mysqltest_1';
delete from mysql.tables_priv where user='mysqltest_1';
delete from mysql.columns_priv where user='mysqltest_1';
flush privileges;
#
# Test what happens when you have same table and colum level grants
#
create table t1 (a int);
GRANT select,update,insert on t1 to mysqltest_1@localhost;
GRANT select (a), update (a),insert(a), references(a) on t1 to mysqltest_1@localhost;
show grants for mysqltest_1@localhost;
select table_priv,column_priv from mysql.tables_priv where user="mysqltest_1";
REVOKE select (a), update on t1 from mysqltest_1@localhost;
show grants for mysqltest_1@localhost;
REVOKE insert,insert (a) on t1 from mysqltest_1@localhost;
GRANT references on t1 to mysqltest_1@localhost;
show grants for mysqltest_1@localhost;
select table_priv,column_priv from mysql.tables_priv where user="mysqltest_1";
delete from mysql.user where user='mysqltest_1';
delete from mysql.db where user='mysqltest_1';
delete from mysql.tables_priv where user='mysqltest_1';
delete from mysql.columns_priv where user='mysqltest_1';
flush privileges;
drop table t1;
/* Copyright (C) 2000 MySQL AB /* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
...@@ -213,8 +213,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) ...@@ -213,8 +213,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
if (table->field[2]->field_length == 8 && if (table->field[2]->field_length == 8 &&
protocol_version == PROTOCOL_VERSION) protocol_version == PROTOCOL_VERSION)
{ {
sql_print_error( sql_print_error("Old 'user' table. (Check README or the Reference manual). Continuing --old-protocol"); /* purecov: tested */
"Old 'user' table. (Check README or the Reference manual). Continuing --old-protocol"); /* purecov: tested */
protocol_version=9; /* purecov: tested */ protocol_version=9; /* purecov: tested */
} }
...@@ -368,7 +367,14 @@ void acl_free(bool end) ...@@ -368,7 +367,14 @@ void acl_free(bool end)
} }
} }
/* Reload acl list if possible */
/*
Forget current privileges and read new privileges from the privilege tables
SYNOPSIS
acl_reload()
thd Thread handle
*/
void acl_reload(THD *thd) void acl_reload(THD *thd)
{ {
...@@ -805,9 +811,10 @@ static void acl_insert_db(const char *user, const char *host, const char *db, ...@@ -805,9 +811,10 @@ static void acl_insert_db(const char *user, const char *host, const char *db,
} }
/*****************************************************************************
** Get privilege for a host, user and db combination /*
*****************************************************************************/ Get privilege for a host, user and db combination
*/
ulong acl_get(const char *host, const char *ip, const char *bin_ip, ulong acl_get(const char *host, const char *ip, const char *bin_ip,
const char *user, const char *db) const char *user, const char *db)
...@@ -929,11 +936,14 @@ int wild_case_compare(const char *str,const char *wildstr) ...@@ -929,11 +936,14 @@ int wild_case_compare(const char *str,const char *wildstr)
DBUG_RETURN (*str != '\0'); DBUG_RETURN (*str != '\0');
} }
/*****************************************************************************
** check if there are any possible matching entries for this host /*
** All host names without wild cards are stored in a hash table, Check if there are any possible matching entries for this host
** entries with wildcards are stored in a dynamic array
*****************************************************************************/ NOTES
All host names without wild cards are stored in a hash table,
entries with wildcards are stored in a dynamic array
*/
static void init_check_host(void) static void init_check_host(void)
{ {
...@@ -1006,10 +1016,6 @@ bool acl_check_host(const char *host, const char *ip) ...@@ -1006,10 +1016,6 @@ bool acl_check_host(const char *host, const char *ip)
return 1; // Host is not allowed return 1; // Host is not allowed
} }
/*****************************************************************************
Change password for the user if it's not an anonymous user
Note: This should write the error directly to the client!
*****************************************************************************/
/* /*
Check if the user is allowed to change password Check if the user is allowed to change password
...@@ -1140,15 +1146,18 @@ find_acl_user(const char *host, const char *user) ...@@ -1140,15 +1146,18 @@ find_acl_user(const char *host, const char *user)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/*****************************************************************************
Handle comparing of hostname /*
Comparing of hostnames
NOTES
A hostname may be of type: A hostname may be of type:
hostname (May include wildcards); monty.pp.sci.fi hostname (May include wildcards); monty.pp.sci.fi
ip (May include wildcards); 192.168.0.0 ip (May include wildcards); 192.168.0.0
ip/netmask 192.168.0.0/255.255.255.0 ip/netmask 192.168.0.0/255.255.255.0
A net mask of 0.0.0.0 is not allowed. A net mask of 0.0.0.0 is not allowed.
*****************************************************************************/ */
static const char *calc_ip(const char *ip, long *val, char end) static const char *calc_ip(const char *ip, long *val, char end)
{ {
...@@ -1195,9 +1204,9 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname, ...@@ -1195,9 +1204,9 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
} }
/**************************************************************************** /*
Code to update grants in the user and database privilege tables Update grants in the user and database privilege tables
****************************************************************************/ */
static bool update_user_table(THD *thd, const char *host, const char *user, static bool update_user_table(THD *thd, const char *host, const char *user,
const char *new_password) const char *new_password)
...@@ -1263,7 +1272,7 @@ static bool test_if_create_new_users(THD *thd) ...@@ -1263,7 +1272,7 @@ static bool test_if_create_new_users(THD *thd)
/**************************************************************************** /****************************************************************************
** Handle GRANT commands Handle GRANT commands
****************************************************************************/ ****************************************************************************/
static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
...@@ -1459,7 +1468,7 @@ static int replace_db_table(TABLE *table, const char *db, ...@@ -1459,7 +1468,7 @@ static int replace_db_table(TABLE *table, const char *db,
char what= (revoke_grant) ? 'N' : 'Y'; char what= (revoke_grant) ? 'N' : 'Y';
DBUG_ENTER("replace_db_table"); DBUG_ENTER("replace_db_table");
// is there such a user in user table in memory ???? /* Check if there is such a user in user table in memory? */
if (!initialized || !find_acl_user(combo.host.str,combo.user.str)) if (!initialized || !find_acl_user(combo.host.str,combo.user.str))
{ {
my_error(ER_PASSWORD_NO_MATCH,MYF(0)); my_error(ER_PASSWORD_NO_MATCH,MYF(0));
...@@ -1502,7 +1511,7 @@ static int replace_db_table(TABLE *table, const char *db, ...@@ -1502,7 +1511,7 @@ static int replace_db_table(TABLE *table, const char *db,
if (old_row_exists) if (old_row_exists)
{ {
// update old existing row /* update old existing row */
if (rights) if (rights)
{ {
if ((error=table->file->update_row(table->record[1],table->record[0]))) if ((error=table->file->update_row(table->record[1],table->record[0])))
...@@ -1529,11 +1538,11 @@ static int replace_db_table(TABLE *table, const char *db, ...@@ -1529,11 +1538,11 @@ static int replace_db_table(TABLE *table, const char *db,
DBUG_RETURN(0); DBUG_RETURN(0);
/* This could only happen if the grant tables got corrupted */ /* This could only happen if the grant tables got corrupted */
table_error: table_error:
table->file->print_error(error,MYF(0)); /* purecov: deadcode */ table->file->print_error(error,MYF(0)); /* purecov: deadcode */
table->file->index_end(); table->file->index_end();
abort: abort:
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
...@@ -1649,7 +1658,7 @@ public: ...@@ -1649,7 +1658,7 @@ public:
if (!(mem_check = new GRANT_COLUMN(*res, if (!(mem_check = new GRANT_COLUMN(*res,
fix_rights_for_column(priv)))) fix_rights_for_column(priv))))
{ {
// Don't use this entry /* Don't use this entry */
privs = cols = 0; /* purecov: deadcode */ privs = cols = 0; /* purecov: deadcode */
return; /* purecov: deadcode */ return; /* purecov: deadcode */
} }
...@@ -1827,7 +1836,7 @@ static int replace_column_table(GRANT_TABLE *g_t, ...@@ -1827,7 +1836,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
key_length, HA_READ_KEY_EXACT)) key_length, HA_READ_KEY_EXACT))
goto end; goto end;
// Scan trough all rows with the same host,db,user and table /* Scan through all rows with the same host,db,user and table */
do do
{ {
ulong privileges = (ulong) table->field[6]->val_int(); ulong privileges = (ulong) table->field[6]->val_int();
...@@ -1877,7 +1886,7 @@ static int replace_column_table(GRANT_TABLE *g_t, ...@@ -1877,7 +1886,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
!key_cmp(table,key,0,key_length)); !key_cmp(table,key,0,key_length));
} }
end: end:
table->file->index_end(); table->file->index_end();
DBUG_RETURN(result); DBUG_RETURN(result);
} }
...@@ -1947,7 +1956,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, ...@@ -1947,7 +1956,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
if (revoke_grant) if (revoke_grant)
{ {
// column rights are already fixed in mysql_table_grant ! /* column rights are already fixed in mysql_table_grant */
store_table_rights=j & ~store_table_rights; store_table_rights=j & ~store_table_rights;
} }
else else
...@@ -1992,18 +2001,35 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, ...@@ -1992,18 +2001,35 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
DBUG_RETURN(0); DBUG_RETURN(0);
/* This should never happen */ /* This should never happen */
table_error: table_error:
table->file->print_error(error,MYF(0)); /* purecov: deadcode */ table->file->print_error(error,MYF(0)); /* purecov: deadcode */
DBUG_RETURN(-1); /* purecov: deadcode */ DBUG_RETURN(-1); /* purecov: deadcode */
} }
/*
Store table level and column level grants in the privilege tables
SYNOPSIS
mysql_table_grant()
thd Thread handle
table_list List of tables to give grant
user_list List of users to give grant
columns List of columns to give grant
rights Table level grant
revoke_grant Set to 1 if this is a REVOKE command
RETURN
0 ok
1 error
*/
int mysql_table_grant(THD *thd, TABLE_LIST *table_list, int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
List <LEX_USER> &user_list, List <LEX_USER> &user_list,
List <LEX_COLUMN> &columns, ulong rights, List <LEX_COLUMN> &columns, ulong rights,
bool revoke_grant) bool revoke_grant)
{ {
ulong column_priv = 0; ulong column_priv= 0;
List_iterator <LEX_USER> str_list (user_list); List_iterator <LEX_USER> str_list (user_list);
LEX_USER *Str; LEX_USER *Str;
TABLE_LIST tables[3]; TABLE_LIST tables[3];
...@@ -2024,21 +2050,21 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, ...@@ -2024,21 +2050,21 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
if (columns.elements && !revoke_grant) if (columns.elements && !revoke_grant)
{ {
TABLE *table; TABLE *table;
class LEX_COLUMN *check; class LEX_COLUMN *column;
List_iterator <LEX_COLUMN> iter(columns); List_iterator <LEX_COLUMN> column_iter(columns);
if (!(table=open_ltable(thd,table_list,TL_READ))) if (!(table=open_ltable(thd,table_list,TL_READ)))
DBUG_RETURN(-1); DBUG_RETURN(-1);
while ((check = iter++)) while ((column = column_iter++))
{ {
if (!find_field_in_table(thd,table,check->column.ptr(), if (!find_field_in_table(thd,table,column->column.ptr(),
check->column.length(),0,0)) column->column.length(),0,0))
{ {
my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0), my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
check->column.c_ptr(), table_list->alias); column->column.c_ptr(), table_list->alias);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
column_priv |= check->rights | (rights & COL_ACLS); column_priv|= column->rights;
} }
close_thread_tables(thd); close_thread_tables(thd);
} }
...@@ -2148,21 +2174,21 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, ...@@ -2148,21 +2174,21 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
/* If revoke_grant, calculate the new column privilege for tables_priv */ /* If revoke_grant, calculate the new column privilege for tables_priv */
if (revoke_grant) if (revoke_grant)
{ {
class LEX_COLUMN *check; class LEX_COLUMN *column;
List_iterator <LEX_COLUMN> iter(columns); List_iterator <LEX_COLUMN> column_iter(columns);
GRANT_COLUMN *grant_column; GRANT_COLUMN *grant_column;
/* Fix old grants */ /* Fix old grants */
while ((check = iter++)) while ((column = column_iter++))
{ {
grant_column = column_hash_search(grant_table, grant_column = column_hash_search(grant_table,
check->column.ptr(), column->column.ptr(),
check->column.length()); column->column.length());
if (grant_column) if (grant_column)
grant_column->rights&= ~(check->rights | rights); grant_column->rights&= ~(column->rights | rights);
} }
/* scan trough all columns to get new column grant */ /* scan trough all columns to get new column grant */
column_priv=0; column_priv= 0;
for (uint idx=0 ; idx < grant_table->hash_columns.records ; idx++) for (uint idx=0 ; idx < grant_table->hash_columns.records ; idx++)
{ {
grant_column= (GRANT_COLUMN*) hash_element(&grant_table->hash_columns, grant_column= (GRANT_COLUMN*) hash_element(&grant_table->hash_columns,
...@@ -2259,7 +2285,7 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list, ...@@ -2259,7 +2285,7 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list,
if (!revoke_grant) if (!revoke_grant)
create_new_users= test_if_create_new_users(thd); create_new_users= test_if_create_new_users(thd);
// go through users in user_list /* go through users in user_list */
pthread_mutex_lock(&LOCK_grant); pthread_mutex_lock(&LOCK_grant);
VOID(pthread_mutex_lock(&acl_cache->lock)); VOID(pthread_mutex_lock(&acl_cache->lock));
grant_version++; grant_version++;
...@@ -2401,7 +2427,16 @@ end: ...@@ -2401,7 +2427,16 @@ end:
} }
/* Reload grant array if possible */ /*
Reload grant array if possible
SYNOPSIS
grant_reload()
thd Thread handler
NOTES
Locked tables are checked by acl_init and doesn't have to be checked here
*/
void grant_reload(THD *thd) void grant_reload(THD *thd)
{ {
...@@ -2410,8 +2445,6 @@ void grant_reload(THD *thd) ...@@ -2410,8 +2445,6 @@ void grant_reload(THD *thd)
MEM_ROOT old_mem; MEM_ROOT old_mem;
DBUG_ENTER("grant_reload"); DBUG_ENTER("grant_reload");
// Locked tables are checked by acl_init and doesn't have to be checked here
pthread_mutex_lock(&LOCK_grant); pthread_mutex_lock(&LOCK_grant);
grant_version++; grant_version++;
old_hash_tables=hash_tables; old_hash_tables=hash_tables;
...@@ -2487,7 +2520,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, ...@@ -2487,7 +2520,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
pthread_mutex_unlock(&LOCK_grant); pthread_mutex_unlock(&LOCK_grant);
return 0; return 0;
err: err:
pthread_mutex_unlock(&LOCK_grant); pthread_mutex_unlock(&LOCK_grant);
if (!no_errors) // Not a silent skip of table if (!no_errors) // Not a silent skip of table
{ {
...@@ -2534,7 +2567,7 @@ bool check_grant_column(THD *thd,TABLE *table, const char *name, ...@@ -2534,7 +2567,7 @@ bool check_grant_column(THD *thd,TABLE *table, const char *name,
pthread_mutex_lock(&LOCK_grant); pthread_mutex_lock(&LOCK_grant);
// reload table if someone has modified any grants /* reload table if someone has modified any grants */
if (table->grant.version != grant_version) if (table->grant.version != grant_version)
{ {
...@@ -2594,7 +2627,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table) ...@@ -2594,7 +2627,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
pthread_mutex_lock(&LOCK_grant); pthread_mutex_lock(&LOCK_grant);
// reload table if someone has modified any grants /* reload table if someone has modified any grants */
if (table->grant.version != grant_version) if (table->grant.version != grant_version)
{ {
...@@ -2604,7 +2637,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table) ...@@ -2604,7 +2637,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
table->real_name,0); /* purecov: inspected */ table->real_name,0); /* purecov: inspected */
table->grant.version=grant_version; /* purecov: inspected */ table->grant.version=grant_version; /* purecov: inspected */
} }
// The following should always be true /* The following should always be true */
if (!(grant_table=table->grant.grant_table)) if (!(grant_table=table->grant.grant_table))
goto err; /* purecov: inspected */ goto err; /* purecov: inspected */
...@@ -2619,7 +2652,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table) ...@@ -2619,7 +2652,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
return 0; return 0;
/* We must use my_printf_error() here! */ /* We must use my_printf_error() here! */
err: err:
pthread_mutex_unlock(&LOCK_grant); pthread_mutex_unlock(&LOCK_grant);
const char *command=""; const char *command="";
...@@ -2639,11 +2672,11 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table) ...@@ -2639,11 +2672,11 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
} }
/**************************************************************************** /*
Check if a user has the right to access a database Check if a user has the right to access a database
Access is accepted if he has a grant for any table in the database Access is accepted if he has a grant for any table in the database
Return 1 if access is denied Return 1 if access is denied
****************************************************************************/ */
bool check_grant_db(THD *thd,const char *db) bool check_grant_db(THD *thd,const char *db)
{ {
...@@ -2683,7 +2716,7 @@ ulong get_table_grant(THD *thd, TABLE_LIST *table) ...@@ -2683,7 +2716,7 @@ ulong get_table_grant(THD *thd, TABLE_LIST *table)
pthread_mutex_lock(&LOCK_grant); pthread_mutex_lock(&LOCK_grant);
grant_table = table_hash_search(thd->host,thd->ip,db,user, grant_table = table_hash_search(thd->host,thd->ip,db,user,
table->real_name,0); table->real_name, 0);
table->grant.grant_table=grant_table; // Remember for column test table->grant.grant_table=grant_table; // Remember for column test
table->grant.version=grant_version; table->grant.version=grant_version;
if (grant_table) if (grant_table)
...@@ -2701,7 +2734,7 @@ ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field) ...@@ -2701,7 +2734,7 @@ ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field)
ulong priv; ulong priv;
pthread_mutex_lock(&LOCK_grant); pthread_mutex_lock(&LOCK_grant);
// reload table if someone has modified any grants /* reload table if someone has modified any grants */
if (table->grant.version != grant_version) if (table->grant.version != grant_version)
{ {
table->grant.grant_table= table->grant.grant_table=
...@@ -2726,11 +2759,20 @@ ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field) ...@@ -2726,11 +2759,20 @@ ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field)
return priv; return priv;
} }
/* Help function for mysql_show_grants */
/***************************************************************************** static void add_user_option(String *grant, ulong value, const char *name)
SHOW GRANTS : send to client grant-like strings depicting user@host {
privileges if (value)
*****************************************************************************/ {
char buff[22], *p; // just as in int2str
grant->append(' ');
grant->append(name, strlen(name));
grant->append(' ');
p=int10_to_str(value, buff, 10);
grant->append(buff,p-buff);
}
}
static const char *command_array[]= static const char *command_array[]=
{ {
...@@ -2739,12 +2781,20 @@ static const char *command_array[]= ...@@ -2739,12 +2781,20 @@ static const char *command_array[]=
"SUPER", "CREATE TEMPORARY TABLES", "LOCK TABLES", "EXECUTE", "SUPER", "CREATE TEMPORARY TABLES", "LOCK TABLES", "EXECUTE",
"REPLICATION SLAVE", "REPLICATION CLIENT", "REPLICATION SLAVE", "REPLICATION CLIENT",
}; };
static uint command_lengths[]= 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 6,6,6,6,6,4,6,8,7,4,5,10,5,5,14,5,23,11,7,17,18
}; };
/*
SHOW GRANTS; Send grants for a user to the client
IMPLEMENTATION
Send to client grant-like strings depicting user@host privileges
*/
int mysql_show_grants(THD *thd,LEX_USER *lex_user) int mysql_show_grants(THD *thd,LEX_USER *lex_user)
{ {
ulong want_access; ulong want_access;
...@@ -2883,27 +2933,12 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) ...@@ -2883,27 +2933,12 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append(" WITH",5); global.append(" WITH",5);
if (want_access & GRANT_ACL) if (want_access & GRANT_ACL)
global.append(" GRANT OPTION",13); global.append(" GRANT OPTION",13);
if (acl_user->user_resource.questions) add_user_option(&global, acl_user->user_resource.questions,
{ "MAX_QUERIES_PER_HOUR");
char buff[22], *p; // just as in int2str add_user_option(&global, acl_user->user_resource.updates,
global.append(" MAX_QUERIES_PER_HOUR ",22); "MAX_UPDATES_PER_HOUR");
p=int10_to_str(acl_user->user_resource.questions,buff,10); add_user_option(&global, acl_user->user_resource.connections,
global.append(buff,p-buff); "MAX_CONNECTIONS_PER_HOUR");
}
if (acl_user->user_resource.updates)
{
char buff[22], *p; // just as in int2str
global.append(" MAX_UPDATES_PER_HOUR ",22);
p=int10_to_str(acl_user->user_resource.updates,buff,10);
global.append(buff,p-buff);
}
if (acl_user->user_resource.connections)
{
char buff[22], *p; // just as in int2str
global.append(" MAX_CONNECTIONS_PER_HOUR ",26);
p=int10_to_str(acl_user->user_resource.connections,buff,10);
global.append(buff,p-buff);
}
} }
thd->packet.length(0); thd->packet.length(0);
net_store_data(&thd->packet,global.ptr(),global.length()); net_store_data(&thd->packet,global.ptr(),global.length());
...@@ -2954,13 +2989,13 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) ...@@ -2954,13 +2989,13 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
} }
} }
} }
db.append (" ON `",5); db.append(" ON `",5);
db.append(acl_db->db); db.append(acl_db->db);
db.append ("`.* TO '",8); db.append("`.* TO '",8);
db.append(lex_user->user.str,lex_user->user.length); db.append(lex_user->user.str,lex_user->user.length);
db.append ("'@'",3); db.append("'@'",3);
db.append(lex_user->host.str, lex_user->host.length); db.append(lex_user->host.str, lex_user->host.length);
db.append ('\''); db.append('\'');
if (want_access & GRANT_ACL) if (want_access & GRANT_ACL)
db.append(" WITH GRANT OPTION",18); db.append(" WITH GRANT OPTION",18);
thd->packet.length(0); thd->packet.length(0);
...@@ -2989,32 +3024,32 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) ...@@ -2989,32 +3024,32 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
if (!strcmp(lex_user->user.str,user) && if (!strcmp(lex_user->user.str,user) &&
!my_strcasecmp(lex_user->host.str,host)) !my_strcasecmp(lex_user->host.str,host))
{ {
want_access=grant_table->privs; ulong table_access= grant_table->privs;
if ((want_access | grant_table->cols) != 0) if ((table_access | grant_table->cols) != 0)
{ {
String global(buff,sizeof(buff)); String global(buff,sizeof(buff));
global.length(0); global.length(0);
global.append("GRANT ",6); global.append("GRANT ",6);
if (test_all_bits(grant_table->privs,(TABLE_ACLS & ~GRANT_ACL))) if (test_all_bits(table_access, (TABLE_ACLS & ~GRANT_ACL)))
global.append("ALL PRIVILEGES",14); global.append("ALL PRIVILEGES",14);
else else
{ {
int found=0; int found= 0;
ulong j,test_access= (want_access | grant_table->cols) & ~GRANT_ACL; ulong j,test_access= (table_access | grant_table->cols) & ~GRANT_ACL;
for (counter=0, j = SELECT_ACL;j <= TABLE_ACLS; counter++,j <<= 1) for (counter= 0, j= SELECT_ACL; j <= TABLE_ACLS; counter++, j<<= 1)
{ {
if (test_access & j) if (test_access & j)
{ {
if (found) if (found)
global.append(", ",2); global.append(", ",2);
found = 1; found= 1;
global.append(command_array[counter],command_lengths[counter]); global.append(command_array[counter],command_lengths[counter]);
if (grant_table->cols) if (grant_table->cols)
{ {
uint found_col=0; uint found_col= 0;
for (uint col_index=0 ; for (uint col_index=0 ;
col_index < grant_table->hash_columns.records ; col_index < grant_table->hash_columns.records ;
col_index++) col_index++)
...@@ -3025,8 +3060,18 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) ...@@ -3025,8 +3060,18 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
{ {
if (!found_col) if (!found_col)
{ {
found_col= 1;
/*
If we have a duplicated table level privilege, we
must write the access privilege name again.
*/
if (table_access & j)
{
global.append(", ", 2);
global.append(command_array[counter],
command_lengths[counter]);
}
global.append(" (",2); global.append(" (",2);
found_col=1;
} }
else else
global.append(", ",2); global.append(", ",2);
...@@ -3049,7 +3094,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) ...@@ -3049,7 +3094,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append("'@'",3); global.append("'@'",3);
global.append(lex_user->host.str,lex_user->host.length); global.append(lex_user->host.str,lex_user->host.length);
global.append('\''); global.append('\'');
if (want_access & GRANT_ACL) if (table_access & GRANT_ACL)
global.append(" WITH GRANT OPTION",18); global.append(" WITH GRANT OPTION",18);
thd->packet.length(0); thd->packet.length(0);
net_store_data(&thd->packet,global.ptr(),global.length()); net_store_data(&thd->packet,global.ptr(),global.length());
...@@ -3063,7 +3108,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) ...@@ -3063,7 +3108,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
} }
} }
end: end:
VOID(pthread_mutex_unlock(&acl_cache->lock)); VOID(pthread_mutex_unlock(&acl_cache->lock));
pthread_mutex_unlock(&LOCK_grant); pthread_mutex_unlock(&LOCK_grant);
......
...@@ -76,8 +76,8 @@ ...@@ -76,8 +76,8 @@
#define get_rights_for_db(A) (((A) & 63) | (((A) & DB_CHUNK1) >> 4) | (((A) & DB_CHUNK2) >> 6)) #define get_rights_for_db(A) (((A) & 63) | (((A) & DB_CHUNK1) >> 4) | (((A) & DB_CHUNK2) >> 6))
#define fix_rights_for_table(A) (((A) & 63) | (((A) & ~63) << 4)) #define fix_rights_for_table(A) (((A) & 63) | (((A) & ~63) << 4))
#define get_rights_for_table(A) (((A) & 63) | (((A) & ~63) >> 4)) #define get_rights_for_table(A) (((A) & 63) | (((A) & ~63) >> 4))
#define fix_rights_for_column(A) (((A) & 7) | (((A) & ~7) << 7)) #define fix_rights_for_column(A) (((A) & 7) | (((A) & ~7) << 8))
#define get_rights_for_column(A) (((A) & 7) | (((A) & ~7) >> 7)) #define get_rights_for_column(A) (((A) & 7) | ((A) >> 8))
/* prototypes */ /* prototypes */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment