@ -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 acl_load ( THD * thd , TABLE_LIST * tables ) ;
static my_bool grant_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 ) ;
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 ,
Convert scrambled password to binary form , according to scramble type ,
Binary form is stored in user . salt .
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 .
Delete from grant structure if drop is true .
Update in grant structure if drop is false and user_to is not NULL .
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 .
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 At least one element matched .
@ retval 0 OK , but no 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 )
LEX_USER * user_from , LEX_USER * user_to )
{
{
int result = 0 ;
int result = 0 ;
@ -5413,6 +5423,11 @@ static int handle_grant_struct(uint struct_no, bool drop,
ACL_USER * acl_user = NULL ;
ACL_USER * acl_user = NULL ;
ACL_DB * acl_db = NULL ;
ACL_DB * acl_db = NULL ;
GRANT_NAME * grant_name = 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 ;
HASH * grant_name_hash = NULL ;
DBUG_ENTER ( " handle_grant_struct " ) ;
DBUG_ENTER ( " handle_grant_struct " ) ;
DBUG_PRINT ( " info " , ( " scan struct: %u search: '%s'@'%s' " ,
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. */
/* Get the number of elements in the in-memory structure. */
switch ( struct_no ) {
switch ( struct_no ) {
case 0 :
case USER_ACL :
elements = acl_users . elements ;
elements = acl_users . elements ;
break ;
break ;
case 1 :
case DB_ACL :
elements = acl_dbs . elements ;
elements = acl_dbs . elements ;
break ;
break ;
case 2 :
case COLUMN_PRIVILEGES_HASH :
elements = column_priv_hash . records ;
elements = column_priv_hash . records ;
grant_name_hash = & column_priv_hash ;
grant_name_hash = & column_priv_hash ;
break ;
break ;
case 3 :
case PROC_PRIVILEGES_HASH :
elements = proc_priv_hash . records ;
elements = proc_priv_hash . records ;
grant_name_hash = & proc_priv_hash ;
grant_name_hash = & proc_priv_hash ;
break ;
break ;
case 4 :
case FUNC_PRIVILEGES_HASH :
elements = func_priv_hash . records ;
elements = func_priv_hash . records ;
grant_name_hash = & func_priv_hash ;
grant_name_hash = & func_priv_hash ;
break ;
break ;
@ -5458,21 +5473,21 @@ static int handle_grant_struct(uint struct_no, bool drop,
Get a pointer to the element .
Get a pointer to the element .
*/
*/
switch ( struct_no ) {
switch ( struct_no ) {
case 0 :
case USER_ACL :
acl_user = dynamic_element ( & acl_users , idx , ACL_USER * ) ;
acl_user = dynamic_element ( & acl_users , idx , ACL_USER * ) ;
user = acl_user - > user ;
user = acl_user - > user ;
host = acl_user - > host . hostname ;
host = acl_user - > host . hostname ;
break ;
break ;
case 1 :
case DB_ACL :
acl_db = dynamic_element ( & acl_dbs , idx , ACL_DB * ) ;
acl_db = dynamic_element ( & acl_dbs , idx , ACL_DB * ) ;
user = acl_db - > user ;
user = acl_db - > user ;
host = acl_db - > host . hostname ;
host = acl_db - > host . hostname ;
break ;
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 ) ;
grant_name = ( GRANT_NAME * ) hash_element ( grant_name_hash , idx ) ;
user = grant_name - > user ;
user = grant_name - > user ;
host = grant_name - > host . hostname ;
host = grant_name - > host . hostname ;
@ -5498,52 +5513,84 @@ static int handle_grant_struct(uint struct_no, bool drop,
if ( drop )
if ( drop )
{
{
switch ( struct_no ) {
switch ( struct_no ) {
case 0 :
case USER_ACL :
delete_dynamic_element ( & acl_users , idx ) ;
delete_dynamic_element ( & acl_users , idx ) ;
break ;
case 1 :
delete_dynamic_element ( & acl_dbs , idx ) ;
break ;
case 2 :
case 3 :
case 4 :
hash_delete ( grant_name_hash , ( uchar * ) grant_name ) ;
break ;
}
elements - - ;
elements - - ;
/*
/*
- If we are iterating through an array then we just have moved all
- If we are iterating through an array then we just have moved all
elements after the current element one position closer to its head .
elements after the current element one position closer to its head .
This means that we have to take another look at the element at
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 .
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 .
- This is valid for USER_ACL , DB_ACL .
*/
*/
idx - - ;
idx - - ;
break ;
case DB_ACL :
delete_dynamic_element ( & acl_dbs , idx ) ;
elements - - ;
idx - - ;
break ;
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 ;
}
}
}
else if ( user_to )
else if ( user_to )
{
{
switch ( struct_no ) {
switch ( struct_no ) {
case 0 :
case USER_ACL :
acl_user - > user = strdup_root ( & mem , user_to - > user . str ) ;
acl_user - > user = strdup_root ( & mem , user_to - > user . str ) ;
acl_user - > host . hostname = strdup_root ( & mem , user_to - > host . str ) ;
acl_user - > host . hostname = strdup_root ( & mem , user_to - > host . str ) ;
break ;
break ;
case 1 :
case DB_ACL :
acl_db - > user = strdup_root ( & mem , user_to - > user . str ) ;
acl_db - > user = strdup_root ( & mem , user_to - > user . str ) ;
acl_db - > host . hostname = strdup_root ( & mem , user_to - > host . str ) ;
acl_db - > host . hostname = strdup_root ( & mem , user_to - > host . str ) ;
break ;
break ;
case 2 :
case 3 :
case 4 :
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
{
/* If search is requested, we do not need to search further. */
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
Save old hash key and its length to be able properly update
@ -5564,28 +5611,12 @@ static int handle_grant_struct(uint struct_no, bool drop,
is renamed , the hash key is changed . Update the hash to
is renamed , the hash key is changed . Update the hash to
ensure that the position matches the new hash key value
ensure that the position matches the new hash key value
*/
*/
hash_update ( grant_name_hash , ( uchar * ) grant_name , ( uchar * ) old_key ,
my_ hash_update( grant_name_hash , ( uchar * ) grant_name , ( uchar * ) old_key ,
old_key_length ) ;
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 ;
}
}
}
}
else
{
/* If search is requested, we do not need to search further. */
break ;
}
}
}
}
# ifdef EXTRA_DEBUG
# ifdef EXTRA_DEBUG
DBUG_PRINT ( " loop " , ( " scan struct: %u result %d " , struct_no , result ) ) ;
DBUG_PRINT ( " loop " , ( " scan struct: %u result %d " , struct_no , result ) ) ;
# endif
# endif
@ -5623,6 +5654,7 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop,
{
{
int result = 0 ;
int result = 0 ;
int found ;
int found ;
int ret ;
DBUG_ENTER ( " handle_grant_data " ) ;
DBUG_ENTER ( " handle_grant_data " ) ;
/* Handle user table. */
/* Handle user table. */
@ -5634,14 +5666,19 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop,
else
else
{
{
/* Handle user array. */
/* 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. */
result = 1 ; /* At least one record/element found. */
/* If search is requested, we do not need to search further. */
/* If search is requested, we do not need to search further. */
if ( ! drop & & ! user_to )
if ( ! drop & & ! user_to )
goto end ;
goto end ;
}
}
else if ( ret < 0 )
{
result = - 1 ;
goto end ;
}
}
}
/* Handle db table. */
/* Handle db table. */
@ -5653,14 +5690,19 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop,
else
else
{
{
/* Handle db array. */
/* 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. */
result = 1 ; /* At least one record/element found. */
/* If search is requested, we do not need to search further. */
/* If search is requested, we do not need to search further. */
if ( ! drop & & ! user_to )
if ( ! drop & & ! user_to )
goto end ;
goto end ;
}
}
else if ( ret < 0 )
{
result = - 1 ;
goto end ;
}
}
}
/* Handle stored routines table. */
/* Handle stored routines table. */
@ -5672,23 +5714,35 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop,
else
else
{
{
/* Handle procs array. */
/* 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. */
result = 1 ; /* At least one record/element found. */
/* If search is requested, we do not need to search further. */
/* If search is requested, we do not need to search further. */
if ( ! drop & & ! user_to )
if ( ! drop & & ! user_to )
goto end ;
goto end ;
}
}
else if ( ret < 0 )
{
result = - 1 ;
goto end ;
}
/* Handle funcs array. */
/* 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. */
result = 1 ; /* At least one record/element found. */
/* If search is requested, we do not need to search further. */
/* If search is requested, we do not need to search further. */
if ( ! drop & & ! user_to )
if ( ! drop & & ! user_to )
goto end ;
goto end ;
}
}
else if ( ret < 0 )
{
result = - 1 ;
goto end ;
}
}
}
/* Handle tables table. */
/* Handle tables table. */
@ -5716,9 +5770,12 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop,
else
else
{
{
/* Handle columns hash. */
/* 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. */
result = 1 ; /* At least one record/element found. */
else if ( ret < 0 )
result = - 1 ;
}
}
}
}
end :
end :