@ -195,7 +195,17 @@ static bool compare_hostname(const acl_host_and_ip *host,const char *hostname,
static my_bool acl_load ( THD * thd , TABLE_LIST * tables ) ;
static my_bool grant_load ( THD * thd , TABLE_LIST * tables ) ;
static inline void get_grantor ( THD * thd , char * grantor ) ;
/*
Enumeration of various ACL ' s and Hashes used in handle_grant_struct ( )
*/
enum enum_acl_lists
{
USER_ACL = 0 ,
DB_ACL ,
COLUMN_PRIVILEGES_HASH ,
PROC_PRIVILEGES_HASH ,
FUNC_PRIVILEGES_HASH
} ;
/*
Convert scrambled password to binary form , according to scramble type ,
Binary form is stored in user . salt .
@ -5390,19 +5400,19 @@ static int handle_grant_table(TABLE_LIST *tables, uint table_no, bool drop,
Delete from grant structure if drop is true .
Update in grant structure if drop is false and user_to is not NULL .
Search in grant structure if drop is false and user_to is NULL .
Structures are numb ered as follows :
0 acl_users
1 acl_dbs
2 column_priv_hash
3 proc_priv_hash
4 func_priv_hash
Structures are e numerat ed as follows :
0 ACL_USER
1 ACL_DB
2 COLUMN_PRIVILEGES_HASH
3 PROC_PRIVILEGES_HASH
4 FUNC_PRIVILEGES_HASH
@ retval > 0 At least one element matched .
@ retval 0 OK , but no element matched .
@ retval - 1 Wrong arguments to function .
@ retval - 1 Wrong arguments to function or Out of Memory
*/
static int handle_grant_struct ( uint struct_no , bool drop ,
static int handle_grant_struct ( enum enum_acl_lists struct_no , bool drop ,
LEX_USER * user_from , LEX_USER * user_to )
{
int result = 0 ;
@ -5413,6 +5423,11 @@ static int handle_grant_struct(uint struct_no, bool drop,
ACL_USER * acl_user = NULL ;
ACL_DB * acl_db = NULL ;
GRANT_NAME * grant_name = NULL ;
/*
Dynamic array acl_grant_name used to store pointers to all
GRANT_NAME objects
*/
Dynamic_array < GRANT_NAME * > acl_grant_name ;
HASH * grant_name_hash = NULL ;
DBUG_ENTER ( " handle_grant_struct " ) ;
DBUG_PRINT ( " info " , ( " scan struct: %u search: '%s'@'%s' " ,
@ -5425,21 +5440,21 @@ static int handle_grant_struct(uint struct_no, bool drop,
/* Get the number of elements in the in-memory structure. */
switch ( struct_no ) {
case 0 :
case USER_ACL :
elements = acl_users . elements ;
break ;
case 1 :
case DB_ACL :
elements = acl_dbs . elements ;
break ;
case 2 :
case COLUMN_PRIVILEGES_HASH :
elements = column_priv_hash . records ;
grant_name_hash = & column_priv_hash ;
break ;
case 3 :
case PROC_PRIVILEGES_HASH :
elements = proc_priv_hash . records ;
grant_name_hash = & proc_priv_hash ;
break ;
case 4 :
case FUNC_PRIVILEGES_HASH :
elements = func_priv_hash . records ;
grant_name_hash = & func_priv_hash ;
break ;
@ -5458,21 +5473,21 @@ static int handle_grant_struct(uint struct_no, bool drop,
Get a pointer to the element .
*/
switch ( struct_no ) {
case 0 :
case USER_ACL :
acl_user = dynamic_element ( & acl_users , idx , ACL_USER * ) ;
user = acl_user - > user ;
host = acl_user - > host . hostname ;
break ;
case 1 :
case DB_ACL :
acl_db = dynamic_element ( & acl_dbs , idx , ACL_DB * ) ;
user = acl_db - > user ;
host = acl_db - > host . hostname ;
break ;
case 2 :
case 3 :
case 4 :
case COLUMN_PRIVILEGES_HASH :
case PROC_PRIVILEGES_HASH :
case FUNC_PRIVILEGES_HASH :
grant_name = ( GRANT_NAME * ) hash_element ( grant_name_hash , idx ) ;
user = grant_name - > user ;
host = grant_name - > host . hostname ;
@ -5498,86 +5513,60 @@ static int handle_grant_struct(uint struct_no, bool drop,
if ( drop )
{
switch ( struct_no ) {
case 0 :
case USER_ACL :
delete_dynamic_element ( & acl_users , idx ) ;
elements - - ;
/*
- If we are iterating through an array then we just have moved all
elements after the current element one position closer to its head .
This means that we have to take another look at the element at
current position as it is a new element from the array ' s tail .
- This is valid for USER_ACL , DB_ACL .
*/
idx - - ;
break ;
case 1 :
case DB_ACL :
delete_dynamic_element ( & acl_dbs , idx ) ;
elements - - ;
idx - - ;
break ;
case 2 :
case 3 :
case 4 :
hash_delete ( grant_name_hash , ( uchar * ) grant_name ) ;
case COLUMN_PRIVILEGES_HASH :
case PROC_PRIVILEGES_HASH :
case FUNC_PRIVILEGES_HASH :
/*
Deleting while traversing a hash table is not valid procedure and
hence we save pointers to GRANT_NAME objects for later processing .
*/
if ( acl_grant_name . append ( grant_name ) )
DBUG_RETURN ( - 1 ) ;
break ;
}
elements - - ;
/*
- If we are iterating through an array then we just have moved all
elements after the current element one position closer to its head .
This means that we have to take another look at the element at
current position as it is a new element from the array ' s tail .
- If we are iterating through a hash the current element was replaced
with one of elements from the tail . So we also have to take a look
at the new element in current position .
Note that in our HASH implementation hash_delete ( ) won ' t move any
elements with position after current one to position before the
current ( i . e . from the tail to the head ) , so it is safe to continue
iteration without re - starting .
*/
idx - - ;
}
else if ( user_to )
{
switch ( struct_no ) {
case 0 :
case USER_ACL :
acl_user - > user = strdup_root ( & mem , user_to - > user . str ) ;
acl_user - > host . hostname = strdup_root ( & mem , user_to - > host . str ) ;
break ;
case 1 :
case DB_ACL :
acl_db - > user = strdup_root ( & mem , user_to - > user . str ) ;
acl_db - > host . hostname = strdup_root ( & mem , user_to - > host . str ) ;
break ;
case 2 :
case 3 :
case 4 :
{
/*
Save old hash key and its length to be able properly update
element position in hash .
*/
char * old_key = grant_name - > hash_key ;
size_t old_key_length = grant_name - > key_length ;
/*
Update the grant structure with the new user name and host name .
*/
grant_name - > set_user_details ( user_to - > host . str , grant_name - > db ,
user_to - > user . str , grant_name - > tname ,
TRUE ) ;
/*
Since username is part of the hash key , when the user name
is renamed , the hash key is changed . Update the hash to
ensure that the position matches the new hash key value
*/
hash_update ( grant_name_hash , ( uchar * ) grant_name , ( uchar * ) old_key ,
old_key_length ) ;
/*
hash_update ( ) operation could have moved element from the tail
of the hash to the current position . So we need to take a look
at the element in current position once again .
Thanks to the fact that hash_update ( ) for our HASH implementation
won ' t move any elements from the tail of the hash to the positions
before the current one ( a . k . a . head ) it is safe to continue
iteration without restarting .
*/
idx - - ;
break ;
}
case COLUMN_PRIVILEGES_HASH :
case PROC_PRIVILEGES_HASH :
case FUNC_PRIVILEGES_HASH :
/*
Updating while traversing a hash table is not valid procedure and
hence we save pointers to GRANT_NAME objects for later processing .
*/
if ( acl_grant_name . append ( grant_name ) )
DBUG_RETURN ( - 1 ) ;
break ;
}
}
else
@ -5586,6 +5575,48 @@ static int handle_grant_struct(uint struct_no, bool drop,
break ;
}
}
if ( drop | | user_to )
{
/*
Traversing the elements stored in acl_grant_name dynamic array
to either delete or update them .
*/
for ( int i = 0 ; i < acl_grant_name . elements ( ) ; + + i )
{
grant_name = acl_grant_name . at ( i ) ;
if ( drop )
{
my_hash_delete ( grant_name_hash , ( uchar * ) grant_name ) ;
}
else
{
/*
Save old hash key and its length to be able properly update
element position in hash .
*/
char * old_key = grant_name - > hash_key ;
size_t old_key_length = grant_name - > key_length ;
/*
Update the grant structure with the new user name and host name .
*/
grant_name - > set_user_details ( user_to - > host . str , grant_name - > db ,
user_to - > user . str , grant_name - > tname ,
TRUE ) ;
/*
Since username is part of the hash key , when the user name
is renamed , the hash key is changed . Update the hash to
ensure that the position matches the new hash key value
*/
my_hash_update ( grant_name_hash , ( uchar * ) grant_name , ( uchar * ) old_key ,
old_key_length ) ;
}
}
}
# ifdef EXTRA_DEBUG
DBUG_PRINT ( " loop " , ( " scan struct: %u result %d " , struct_no , result ) ) ;
# endif
@ -5623,6 +5654,7 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop,
{
int result = 0 ;
int found ;
int ret ;
DBUG_ENTER ( " handle_grant_data " ) ;
/* Handle user table. */
@ -5634,14 +5666,19 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop,
else
{
/* Handle user array. */
if ( ( handle_grant_struct ( 0 , drop , user_from , user_to ) & & ! result ) | |
found )
if ( ( ( ret = handle_grant_struct ( USER_ACL , drop , user_from , user_to ) > 0 ) & &
! result ) | | found )
{
result = 1 ; /* At least one record/element found. */
/* If search is requested, we do not need to search further. */
if ( ! drop & & ! user_to )
goto end ;
}
else if ( ret < 0 )
{
result = - 1 ;
goto end ;
}
}
/* Handle db table. */
@ -5653,14 +5690,19 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop,
else
{
/* Handle db array. */
if ( ( ( handle_grant_struct ( 1 , drop , user_from , user_to ) & & ! result ) | |
found ) & & ! result )
if ( ( ( ( ret = handle_grant_struct ( DB_ACL , drop , user_from , user_to ) > 0 ) & &
! result ) | | found ) & & ! result )
{
result = 1 ; /* At least one record/element found. */
/* If search is requested, we do not need to search further. */
if ( ! drop & & ! user_to )
goto end ;
}
else if ( ret < 0 )
{
result = - 1 ;
goto end ;
}
}
/* Handle stored routines table. */
@ -5672,23 +5714,35 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop,
else
{
/* Handle procs array. */
if ( ( ( handle_grant_struct ( 3 , drop , user_from , user_to ) & & ! result ) | |
found ) & & ! result )
if ( ( ( ( ret = handle_grant_struct ( PROC_PRIVILEGES_HASH , drop , user_from ,
user_to ) > 0 ) & & ! result ) | | found ) & &
! result )
{
result = 1 ; /* At least one record/element found. */
/* If search is requested, we do not need to search further. */
if ( ! drop & & ! user_to )
goto end ;
}
else if ( ret < 0 )
{
result = - 1 ;
goto end ;
}
/* Handle funcs array. */
if ( ( ( handle_grant_struct ( 4 , drop , user_from , user_to ) & & ! result ) | |
found ) & & ! result )
if ( ( ( ( ret = handle_grant_struct ( FUNC_PRIVILEGES_HASH , drop , user_from ,
user_to ) > 0 ) & & ! result ) | | found ) & &
! result )
{
result = 1 ; /* At least one record/element found. */
/* If search is requested, we do not need to search further. */
if ( ! drop & & ! user_to )
goto end ;
}
else if ( ret < 0 )
{
result = - 1 ;
goto end ;
}
}
/* Handle tables table. */
@ -5716,9 +5770,12 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop,
else
{
/* Handle columns hash. */
if ( ( ( handle_grant_struct ( 2 , drop , user_from , user_to ) & & ! result ) | |
found ) & & ! result )
if ( ( ( ( ret = handle_grant_struct ( COLUMN_PRIVILEGES_HASH , drop , user_from ,
user_to ) > 0 ) & & ! result ) | | found ) & &
! result )
result = 1 ; /* At least one record/element found. */
else if ( ret < 0 )
result = - 1 ;
}
}
end :