Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
0683c122
Commit
0683c122
authored
Sep 01, 2005
by
dlenev@mysql.com
Browse files
Options
Browse Files
Download
Plain Diff
Merge bk-internal.mysql.com:/home/bk/mysql-4.1
into mysql.com:/home/dlenev/src/mysql-4.1-bg12423
parents
b6889a4e
da2af0bb
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
320 additions
and
171 deletions
+320
-171
mysql-test/r/grant2.result
mysql-test/r/grant2.result
+9
-0
mysql-test/t/grant2.test
mysql-test/t/grant2.test
+43
-0
sql/mysqld.cc
sql/mysqld.cc
+2
-2
sql/sql_acl.cc
sql/sql_acl.cc
+241
-161
sql/sql_acl.h
sql/sql_acl.h
+4
-4
sql/sql_parse.cc
sql/sql_parse.cc
+21
-4
No files found.
mysql-test/r/grant2.result
View file @
0683c122
...
@@ -122,3 +122,12 @@ flush privileges;
...
@@ -122,3 +122,12 @@ flush privileges;
drop database mysqltest_1;
drop database mysqltest_1;
set password = password("changed");
set password = password("changed");
ERROR 42000: Access denied for user ''@'localhost' to database 'mysql'
ERROR 42000: Access denied for user ''@'localhost' to database 'mysql'
lock table mysql.user write;
flush privileges;
grant all on *.* to 'mysqltest_1'@'localhost';
unlock tables;
lock table mysql.user write;
set password for 'mysqltest_1'@'localhost' = password('');
revoke all on *.* from 'mysqltest_1'@'localhost';
unlock tables;
drop user 'mysqltest_1'@'localhost';
mysql-test/t/grant2.test
View file @
0683c122
...
@@ -163,4 +163,47 @@ set password = password("changed");
...
@@ -163,4 +163,47 @@ set password = password("changed");
disconnect
n5
;
disconnect
n5
;
connection
default
;
connection
default
;
# Bug #12423 "Deadlock when doing FLUSH PRIVILEGES and GRANT in
# multi-threaded environment". We should be able to execute FLUSH
# PRIVILEGES and SET PASSWORD simultaneously with other account
# management commands (such as GRANT and REVOKE) without causing
# deadlocks. To achieve this we should ensure that all account
# management commands take table and internal locks in the same order.
connect
(
con2root
,
localhost
,
root
,,);
connect
(
con3root
,
localhost
,
root
,,);
# Check that we can execute FLUSH PRIVILEGES and GRANT simultaneously
# This will check that locks are taken in proper order during both
# user/db-level and table/column-level privileges reloading.
connection
default
;
lock
table
mysql
.
user
write
;
connection
con2root
;
send
flush
privileges
;
connection
con3root
;
send
grant
all
on
*.*
to
'mysqltest_1'
@
'localhost'
;
connection
default
;
unlock
tables
;
connection
con2root
;
reap
;
connection
con3root
;
reap
;
# Check for simultaneous SET PASSWORD and REVOKE.
connection
default
;
lock
table
mysql
.
user
write
;
connection
con2root
;
send
set
password
for
'mysqltest_1'
@
'localhost'
=
password
(
''
);
connection
con3root
;
send
revoke
all
on
*.*
from
'mysqltest_1'
@
'localhost'
;
connection
default
;
unlock
tables
;
connection
con2root
;
reap
;
connection
con3root
;
reap
;
connection
default
;
# Clean-up
drop
user
'mysqltest_1'
@
'localhost'
;
disconnect
con2root
;
disconnect
con3root
;
# End of 4.1 tests
# End of 4.1 tests
sql/mysqld.cc
View file @
0683c122
...
@@ -3080,7 +3080,7 @@ we force server id to 2, but this MySQL server will not act as a slave.");
...
@@ -3080,7 +3080,7 @@ we force server id to 2, but this MySQL server will not act as a slave.");
*/
*/
error_handler_hook
=
my_message_sql
;
error_handler_hook
=
my_message_sql
;
start_signal_handler
();
// Creates pidfile
start_signal_handler
();
// Creates pidfile
if
(
acl_init
(
(
THD
*
)
0
,
opt_noacl
)
||
if
(
acl_init
(
opt_noacl
)
||
my_tz_init
((
THD
*
)
0
,
default_tz_name
,
opt_bootstrap
))
my_tz_init
((
THD
*
)
0
,
default_tz_name
,
opt_bootstrap
))
{
{
abort_loop
=
1
;
abort_loop
=
1
;
...
@@ -3097,7 +3097,7 @@ we force server id to 2, but this MySQL server will not act as a slave.");
...
@@ -3097,7 +3097,7 @@ we force server id to 2, but this MySQL server will not act as a slave.");
exit
(
1
);
exit
(
1
);
}
}
if
(
!
opt_noacl
)
if
(
!
opt_noacl
)
(
void
)
grant_init
(
(
THD
*
)
0
);
(
void
)
grant_init
();
#ifdef HAVE_DLOPEN
#ifdef HAVE_DLOPEN
if
(
!
opt_noacl
)
if
(
!
opt_noacl
)
...
...
sql/sql_acl.cc
View file @
0683c122
...
@@ -62,18 +62,21 @@ static HASH acl_check_hosts, column_priv_hash;
...
@@ -62,18 +62,21 @@ static HASH acl_check_hosts, column_priv_hash;
static
DYNAMIC_ARRAY
acl_wild_hosts
;
static
DYNAMIC_ARRAY
acl_wild_hosts
;
static
hash_filo
*
acl_cache
;
static
hash_filo
*
acl_cache
;
static
uint
grant_version
=
0
;
static
uint
grant_version
=
0
;
static
uint
priv_version
=
0
;
/* Version of priv tables. incremented by acl_
init
*/
static
uint
priv_version
=
0
;
/* Version of priv tables. incremented by acl_
load
*/
static
ulong
get_access
(
TABLE
*
form
,
uint
fieldnr
,
uint
*
next_field
=
0
);
static
ulong
get_access
(
TABLE
*
form
,
uint
fieldnr
,
uint
*
next_field
=
0
);
static
int
acl_compare
(
ACL_ACCESS
*
a
,
ACL_ACCESS
*
b
);
static
int
acl_compare
(
ACL_ACCESS
*
a
,
ACL_ACCESS
*
b
);
static
ulong
get_sort
(
uint
count
,...);
static
ulong
get_sort
(
uint
count
,...);
static
void
init_check_host
(
void
);
static
void
init_check_host
(
void
);
static
ACL_USER
*
find_acl_user
(
const
char
*
host
,
const
char
*
user
,
static
ACL_USER
*
find_acl_user
(
const
char
*
host
,
const
char
*
user
,
my_bool
exact
);
my_bool
exact
);
static
bool
update_user_table
(
THD
*
thd
,
const
char
*
host
,
const
char
*
user
,
static
bool
update_user_table
(
THD
*
thd
,
TABLE
*
table
,
const
char
*
host
,
const
char
*
user
,
const
char
*
new_password
,
uint
new_password_len
);
const
char
*
new_password
,
uint
new_password_len
);
static
void
update_hostname
(
acl_host_and_ip
*
host
,
const
char
*
hostname
);
static
void
update_hostname
(
acl_host_and_ip
*
host
,
const
char
*
hostname
);
static
bool
compare_hostname
(
const
acl_host_and_ip
*
host
,
const
char
*
hostname
,
static
bool
compare_hostname
(
const
acl_host_and_ip
*
host
,
const
char
*
hostname
,
const
char
*
ip
);
const
char
*
ip
);
static
my_bool
acl_load
(
THD
*
thd
,
TABLE_LIST
*
tables
);
static
my_bool
grant_load
(
TABLE_LIST
*
tables
);
/*
/*
Convert scrambled password to binary form, according to scramble type,
Convert scrambled password to binary form, according to scramble type,
...
@@ -118,79 +121,84 @@ static void restrict_update_of_old_passwords_var(THD *thd,
...
@@ -118,79 +121,84 @@ static void restrict_update_of_old_passwords_var(THD *thd,
/*
/*
Read grant privileges from the privilege tables in the 'mysql' database.
Initialize structures responsible for user/db-level privilege checking and
load privilege information for them from tables in the 'mysql' database.
SYNOPSIS
SYNOPSIS
acl_init()
acl_init()
thd Thread handler
dont_read_acl_tables TRUE if we want to skip loading data from
dont_read_acl_tables Set to 1 if run with --skip-grant
privilege tables and disable privilege checking.
NOTES
This function is mostly responsible for preparatory steps, main work
on initialization and grants loading is done in acl_reload().
RETURN VALUES
RETURN VALUES
0 ok
0 ok
1 Could not initialize grant's
1 Could not initialize grant's
*/
*/
my_bool
acl_init
(
bool
dont_read_acl_tables
)
my_bool
acl_init
(
THD
*
org_thd
,
bool
dont_read_acl_tables
)
{
{
THD
*
thd
;
THD
*
thd
;
TABLE_LIST
tables
[
3
];
my_bool
return_val
;
TABLE
*
table
;
READ_RECORD
read_record_info
;
MYSQL_LOCK
*
lock
;
my_bool
return_val
=
1
;
bool
check_no_resolve
=
specialflag
&
SPECIAL_NO_RESOLVE
;
char
tmp_name
[
NAME_LEN
+
1
];
DBUG_ENTER
(
"acl_init"
);
DBUG_ENTER
(
"acl_init"
);
if
(
!
acl_cache
)
acl_cache
=
new
hash_filo
(
ACL_CACHE_SIZE
,
0
,
0
,
acl_cache
=
new
hash_filo
(
ACL_CACHE_SIZE
,
0
,
0
,
(
hash_get_key
)
acl_entry_get_key
,
(
hash_get_key
)
acl_entry_get_key
,
(
hash_free_key
)
free
,
system_charset_info
);
(
hash_free_key
)
free
,
system_charset_info
);
if
(
dont_read_acl_tables
)
if
(
dont_read_acl_tables
)
{
{
DBUG_RETURN
(
0
);
/* purecov: tested */
DBUG_RETURN
(
0
);
/* purecov: tested */
}
}
priv_version
++
;
/* Privileges updated */
/*
/*
To be able to run this from boot, we allocate a temporary THD
To be able to run this from boot, we allocate a temporary THD
*/
*/
if
(
!
(
thd
=
new
THD
))
if
(
!
(
thd
=
new
THD
))
DBUG_RETURN
(
1
);
/* purecov: inspected */
DBUG_RETURN
(
1
);
/* purecov: inspected */
thd
->
store_globals
();
thd
->
store_globals
();
/*
It is safe to call acl_reload() since acl_* arrays and hashes which
will be freed there are global static objects and thus are initialized
by zeros at startup.
*/
return_val
=
acl_reload
(
thd
);
delete
thd
;
/* Remember that we don't have a THD */
my_pthread_setspecific_ptr
(
THR_THD
,
0
);
DBUG_RETURN
(
return_val
);
}
/*
Initialize structures responsible for user/db-level privilege checking
and load information about grants from open privilege tables.
SYNOPSIS
acl_load()
thd Current thread
tables List containing open "mysql.host", "mysql.user" and
"mysql.db" tables.
RETURN VALUES
FALSE Success
TRUE Error
*/
static
my_bool
acl_load
(
THD
*
thd
,
TABLE_LIST
*
tables
)
{
TABLE
*
table
;
READ_RECORD
read_record_info
;
my_bool
return_val
=
1
;
bool
check_no_resolve
=
specialflag
&
SPECIAL_NO_RESOLVE
;
char
tmp_name
[
NAME_LEN
+
1
];
DBUG_ENTER
(
"acl_load"
);
priv_version
++
;
/* Privileges updated */
acl_cache
->
clear
(
1
);
// Clear locked hostname cache
acl_cache
->
clear
(
1
);
// Clear locked hostname cache
thd
->
db
=
my_strdup
(
"mysql"
,
MYF
(
0
));
thd
->
db_length
=
5
;
// Safety
bzero
((
char
*
)
&
tables
,
sizeof
(
tables
));
tables
[
0
].
alias
=
tables
[
0
].
real_name
=
(
char
*
)
"host"
;
tables
[
1
].
alias
=
tables
[
1
].
real_name
=
(
char
*
)
"user"
;
tables
[
2
].
alias
=
tables
[
2
].
real_name
=
(
char
*
)
"db"
;
tables
[
0
].
next
=
tables
+
1
;
tables
[
1
].
next
=
tables
+
2
;
tables
[
0
].
lock_type
=
tables
[
1
].
lock_type
=
tables
[
2
].
lock_type
=
TL_READ
;
tables
[
0
].
db
=
tables
[
1
].
db
=
tables
[
2
].
db
=
thd
->
db
;
uint
counter
;
if
(
open_tables
(
thd
,
tables
,
&
counter
))
{
sql_print_error
(
"Fatal error: Can't open privilege tables: %s"
,
thd
->
net
.
last_error
);
goto
end
;
}
TABLE
*
ptr
[
3
];
// Lock tables for quick update
ptr
[
0
]
=
tables
[
0
].
table
;
ptr
[
1
]
=
tables
[
1
].
table
;
ptr
[
2
]
=
tables
[
2
].
table
;
if
(
!
(
lock
=
mysql_lock_tables
(
thd
,
ptr
,
3
,
0
)))
{
sql_print_error
(
"Fatal error: Can't lock privilege tables: %s"
,
thd
->
net
.
last_error
);
goto
end
;
}
init_sql_alloc
(
&
mem
,
ACL_ALLOC_BLOCK_SIZE
,
0
);
init_sql_alloc
(
&
mem
,
ACL_ALLOC_BLOCK_SIZE
,
0
);
init_read_record
(
&
read_record_info
,
thd
,
table
=
tables
[
0
].
table
,
NULL
,
1
,
0
);
init_read_record
(
&
read_record_info
,
thd
,
table
=
tables
[
0
].
table
,
NULL
,
1
,
0
);
VOID
(
my_init_dynamic_array
(
&
acl_hosts
,
sizeof
(
ACL_HOST
),
20
,
50
));
VOID
(
my_init_dynamic_array
(
&
acl_hosts
,
sizeof
(
ACL_HOST
),
20
,
50
));
...
@@ -432,21 +440,10 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
...
@@ -432,21 +440,10 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
freeze_size
(
&
acl_dbs
);
freeze_size
(
&
acl_dbs
);
init_check_host
();
init_check_host
();
mysql_unlock_tables
(
thd
,
lock
);
initialized
=
1
;
initialized
=
1
;
thd
->
version
--
;
// Force close to free memory
return_val
=
0
;
return_val
=
0
;
end:
end:
close_thread_tables
(
thd
);
delete
thd
;
if
(
org_thd
)
org_thd
->
store_globals
();
/* purecov: inspected */
else
{
/* Remember that we don't have a THD */
my_pthread_setspecific_ptr
(
THR_THD
,
0
);
}
DBUG_RETURN
(
return_val
);
DBUG_RETURN
(
return_val
);
}
}
...
@@ -470,26 +467,60 @@ void acl_free(bool end)
...
@@ -470,26 +467,60 @@ void acl_free(bool end)
/*
/*
Forget current privileges and read new privileges from the privilege tables
Forget current user/db-level privileges and read new privileges
from the privilege tables.
SYNOPSIS
SYNOPSIS
acl_reload()
acl_reload()
thd Thread handle (can be NULL)
thd Current thread
NOTE
All tables of calling thread which were open and locked by LOCK TABLES
statement will be unlocked and closed.
This function is also used for initialization of structures responsible
for user/db-level privilege checking.
RETURN VALUE
FALSE Success
TRUE Failure
*/
*/
void
acl_reload
(
THD
*
thd
)
my_bool
acl_reload
(
THD
*
thd
)
{
{
TABLE_LIST
tables
[
3
];
DYNAMIC_ARRAY
old_acl_hosts
,
old_acl_users
,
old_acl_dbs
;
DYNAMIC_ARRAY
old_acl_hosts
,
old_acl_users
,
old_acl_dbs
;
MEM_ROOT
old_mem
;
MEM_ROOT
old_mem
;
bool
old_initialized
;
bool
old_initialized
;
my_bool
return_val
=
1
;
DBUG_ENTER
(
"acl_reload"
);
DBUG_ENTER
(
"acl_reload"
);
if
(
thd
&&
thd
->
locked_tables
)
if
(
thd
->
locked_tables
)
{
// Can't have locked tables here
{
// Can't have locked tables here
thd
->
lock
=
thd
->
locked_tables
;
thd
->
lock
=
thd
->
locked_tables
;
thd
->
locked_tables
=
0
;
thd
->
locked_tables
=
0
;
close_thread_tables
(
thd
);
close_thread_tables
(
thd
);
}
}
/*
To avoid deadlocks we should obtain table locks before
obtaining acl_cache->lock mutex.
*/
bzero
((
char
*
)
tables
,
sizeof
(
tables
));
tables
[
0
].
alias
=
tables
[
0
].
real_name
=
(
char
*
)
"host"
;
tables
[
1
].
alias
=
tables
[
1
].
real_name
=
(
char
*
)
"user"
;
tables
[
2
].
alias
=
tables
[
2
].
real_name
=
(
char
*
)
"db"
;
tables
[
0
].
db
=
tables
[
1
].
db
=
tables
[
2
].
db
=
(
char
*
)
"mysql"
;
tables
[
0
].
next
=
tables
+
1
;
tables
[
1
].
next
=
tables
+
2
;
tables
[
0
].
lock_type
=
tables
[
1
].
lock_type
=
tables
[
2
].
lock_type
=
TL_READ
;
if
(
simple_open_n_lock_tables
(
thd
,
tables
))
{
sql_print_error
(
"Fatal error: Can't open and lock privilege tables: %s"
,
thd
->
net
.
last_error
);
goto
end
;
}
if
((
old_initialized
=
initialized
))
if
((
old_initialized
=
initialized
))
VOID
(
pthread_mutex_lock
(
&
acl_cache
->
lock
));
VOID
(
pthread_mutex_lock
(
&
acl_cache
->
lock
));
...
@@ -500,7 +531,7 @@ void acl_reload(THD *thd)
...
@@ -500,7 +531,7 @@ void acl_reload(THD *thd)
delete_dynamic
(
&
acl_wild_hosts
);
delete_dynamic
(
&
acl_wild_hosts
);
hash_free
(
&
acl_check_hosts
);
hash_free
(
&
acl_check_hosts
);
if
(
acl_init
(
thd
,
0
))
if
(
(
return_val
=
acl_load
(
thd
,
tables
)
))
{
// Error. Revert to old list
{
// Error. Revert to old list
DBUG_PRINT
(
"error"
,(
"Reverting to old privileges"
));
DBUG_PRINT
(
"error"
,(
"Reverting to old privileges"
));
acl_free
();
/* purecov: inspected */
acl_free
();
/* purecov: inspected */
...
@@ -519,7 +550,9 @@ void acl_reload(THD *thd)
...
@@ -519,7 +550,9 @@ void acl_reload(THD *thd)
}
}
if
(
old_initialized
)
if
(
old_initialized
)
VOID
(
pthread_mutex_unlock
(
&
acl_cache
->
lock
));
VOID
(
pthread_mutex_unlock
(
&
acl_cache
->
lock
));
DBUG_VOID_RETURN
;
end:
close_thread_tables
(
thd
);
DBUG_RETURN
(
return_val
);
}
}
...
@@ -1230,7 +1263,13 @@ bool check_change_password(THD *thd, const char *host, const char *user,
...
@@ -1230,7 +1263,13 @@ bool check_change_password(THD *thd, const char *host, const char *user,
bool
change_password
(
THD
*
thd
,
const
char
*
host
,
const
char
*
user
,
bool
change_password
(
THD
*
thd
,
const
char
*
host
,
const
char
*
user
,
char
*
new_password
)
char
*
new_password
)
{
{
TABLE_LIST
tables
;
TABLE
*
table
;
/* Buffer should be extended when password length is extended. */
char
buff
[
512
];
ulong
query_length
;
uint
new_password_len
=
strlen
(
new_password
);
uint
new_password_len
=
strlen
(
new_password
);
bool
result
=
1
;
DBUG_ENTER
(
"change_password"
);
DBUG_ENTER
(
"change_password"
);
DBUG_PRINT
(
"enter"
,(
"host: '%s' user: '%s' new_password: '%s'"
,
DBUG_PRINT
(
"enter"
,(
"host: '%s' user: '%s' new_password: '%s'"
,
host
,
user
,
new_password
));
host
,
user
,
new_password
));
...
@@ -1239,42 +1278,71 @@ bool change_password(THD *thd, const char *host, const char *user,
...
@@ -1239,42 +1278,71 @@ bool change_password(THD *thd, const char *host, const char *user,
if
(
check_change_password
(
thd
,
host
,
user
,
new_password
,
new_password_len
))
if
(
check_change_password
(
thd
,
host
,
user
,
new_password
,
new_password_len
))
DBUG_RETURN
(
1
);
DBUG_RETURN
(
1
);
bzero
((
char
*
)
&
tables
,
sizeof
(
tables
));
tables
.
alias
=
tables
.
real_name
=
(
char
*
)
"user"
;
tables
.
db
=
(
char
*
)
"mysql"
;
#ifdef HAVE_REPLICATION
/*
GRANT and REVOKE are applied the slave in/exclusion rules as they are
some kind of updates to the mysql.% tables.
*/
if
(
thd
->
slave_thread
&&
table_rules_on
)
{
/*
The tables must be marked "updating" so that tables_ok() takes them into
account in tests. It's ok to leave 'updating' set after tables_ok.
*/
tables
.
updating
=
1
;
/* Thanks to bzero, tables.next==0 */
if
(
!
tables_ok
(
0
,
&
tables
))
DBUG_RETURN
(
0
);
}
#endif
if
(
!
(
table
=
open_ltable
(
thd
,
&
tables
,
TL_WRITE
)))
DBUG_RETURN
(
1
);
VOID
(
pthread_mutex_lock
(
&
acl_cache
->
lock
));
VOID
(
pthread_mutex_lock
(
&
acl_cache
->
lock
));
ACL_USER
*
acl_user
;
ACL_USER
*
acl_user
;
if
(
!
(
acl_user
=
find_acl_user
(
host
,
user
,
TRUE
)))
if
(
!
(
acl_user
=
find_acl_user
(
host
,
user
,
TRUE
)))
{
{
VOID
(
pthread_mutex_unlock
(
&
acl_cache
->
lock
));
VOID
(
pthread_mutex_unlock
(
&
acl_cache
->
lock
));
send_error
(
thd
,
ER_PASSWORD_NO_MATCH
);
send_error
(
thd
,
ER_PASSWORD_NO_MATCH
);
DBUG_RETURN
(
1
)
;
goto
end
;
}
}
/* update loaded acl entry: */
/* update loaded acl entry: */
set_user_salt
(
acl_user
,
new_password
,
new_password_len
);
set_user_salt
(
acl_user
,
new_password
,
new_password_len
);
if
(
update_user_table
(
thd
,
if
(
update_user_table
(
thd
,
table
,
acl_user
->
host
.
hostname
?
acl_user
->
host
.
hostname
:
""
,
acl_user
->
host
.
hostname
?
acl_user
->
host
.
hostname
:
""
,
acl_user
->
user
?
acl_user
->
user
:
""
,
acl_user
->
user
?
acl_user
->
user
:
""
,
new_password
,
new_password_len
))
new_password
,
new_password_len
))
{
{
VOID
(
pthread_mutex_unlock
(
&
acl_cache
->
lock
));
/* purecov: deadcode */
VOID
(
pthread_mutex_unlock
(
&
acl_cache
->
lock
));
/* purecov: deadcode */
send_error
(
thd
,
0
);
/* purecov: deadcode */
send_error
(
thd
,
0
);
/* purecov: deadcode */
DBUG_RETURN
(
1
);
/* purecov: deadcode */
goto
end
;
}
}
acl_cache
->
clear
(
1
);
// Clear locked hostname cache
acl_cache
->
clear
(
1
);
// Clear locked hostname cache
VOID
(
pthread_mutex_unlock
(
&
acl_cache
->
lock
));
VOID
(
pthread_mutex_unlock
(
&
acl_cache
->
lock
));
result
=
0
;
char
buff
[
512
];
/* Extend with extended password length*/
query_length
=
ulong
query_length
=
my_sprintf
(
buff
,
my_sprintf
(
buff
,
(
buff
,
"SET PASSWORD FOR
\"
%-.120s
\"
@
\"
%-.120s
\"
=
\"
%-.120s
\"
"
,
(
buff
,
"SET PASSWORD FOR
\"
%-.120s
\"
@
\"
%-.120s
\"
=
\"
%-.120s
\"
"
,
acl_user
->
user
?
acl_user
->
user
:
""
,
acl_user
->
user
?
acl_user
->
user
:
""
,
acl_user
->
host
.
hostname
?
acl_user
->
host
.
hostname
:
""
,
acl_user
->
host
.
hostname
?
acl_user
->
host
.
hostname
:
""
,
new_password
));
new_password
));
thd
->
clear_error
();
mysql_update_log
.
write
(
thd
,
buff
,
query_length
);
mysql_update_log
.
write
(
thd
,
buff
,
query_length
);
Query_log_event
qinfo
(
thd
,
buff
,
query_length
,
0
,
FALSE
);
if
(
mysql_bin_log
.
is_open
())
mysql_bin_log
.
write
(
&
qinfo
);
{
DBUG_RETURN
(
0
);
thd
->
clear_error
();
Query_log_event
qinfo
(
thd
,
buff
,
query_length
,
0
,
FALSE
);
mysql_bin_log
.
write
(
&
qinfo
);
}
end:
close_thread_tables
(
thd
);
DBUG_RETURN
(
result
);
}
}
...
@@ -1388,43 +1456,28 @@ bool hostname_requires_resolving(const char *hostname)
...
@@ -1388,43 +1456,28 @@ bool hostname_requires_resolving(const char *hostname)
return
FALSE
;
return
FALSE
;
}
}
/*
/*
Update grants in the user and database privilege tables
Update record for user in mysql.user privilege table with new password.
SYNOPSIS
update_user_table()
thd Thread handle
table Pointer to TABLE object for open mysql.user table
host/user Hostname/username pair identifying user for which
new password should be set
new_password New password
new_password_len Length of new password
*/
*/
static
bool
update_user_table
(
THD
*
thd
,
const
char
*
host
,
const
char
*
user
,
static
bool
update_user_table
(
THD
*
thd
,
TABLE
*
table
,
const
char
*
host
,
const
char
*
user
,
const
char
*
new_password
,
uint
new_password_len
)
const
char
*
new_password
,
uint
new_password_len
)
{
{
TABLE_LIST
tables
;
int
error
;
TABLE
*
table
;
bool
error
=
1
;
DBUG_ENTER
(
"update_user_table"
);
DBUG_ENTER
(
"update_user_table"
);
DBUG_PRINT
(
"enter"
,(
"user: %s host: %s"
,
user
,
host
));
DBUG_PRINT
(
"enter"
,(
"user: %s host: %s"
,
user
,
host
));
bzero
((
char
*
)
&
tables
,
sizeof
(
tables
));
tables
.
alias
=
tables
.
real_name
=
(
char
*
)
"user"
;
tables
.
db
=
(
char
*
)
"mysql"
;
#ifdef HAVE_REPLICATION
/*
GRANT and REVOKE are applied the slave in/exclusion rules as they are
some kind of updates to the mysql.% tables.
*/
if
(
thd
->
slave_thread
&&
table_rules_on
)
{
/*
The tables must be marked "updating" so that tables_ok() takes them into
account in tests. It's ok to leave 'updating' set after tables_ok.
*/
tables
.
updating
=
1
;
/* Thanks to bzero, tables.next==0 */
if
(
!
tables_ok
(
0
,
&
tables
))
DBUG_RETURN
(
0
);
}
#endif
if
(
!
(
table
=
open_ltable
(
thd
,
&
tables
,
TL_WRITE
)))
DBUG_RETURN
(
1
);
/* purecov: deadcode */
table
->
field
[
0
]
->
store
(
host
,(
uint
)
strlen
(
host
),
&
my_charset_latin1
);
table
->
field
[
0
]
->
store
(
host
,(
uint
)
strlen
(
host
),
&
my_charset_latin1
);
table
->
field
[
1
]
->
store
(
user
,(
uint
)
strlen
(
user
),
&
my_charset_latin1
);
table
->
field
[
1
]
->
store
(
user
,(
uint
)
strlen
(
user
),
&
my_charset_latin1
);
...
@@ -1442,13 +1495,9 @@ static bool update_user_table(THD *thd, const char *host, const char *user,
...
@@ -1442,13 +1495,9 @@ static bool update_user_table(THD *thd, const char *host, const char *user,
if
((
error
=
table
->
file
->
update_row
(
table
->
record
[
1
],
table
->
record
[
0
])))
if
((
error
=
table
->
file
->
update_row
(
table
->
record
[
1
],
table
->
record
[
0
])))
{
{
table
->
file
->
print_error
(
error
,
MYF
(
0
));
/* purecov: deadcode */
table
->
file
->
print_error
(
error
,
MYF
(
0
));
/* purecov: deadcode */
goto
end
;
/* purecov: deadcode */
DBUG_RETURN
(
1
);
}
}
error
=
0
;
// Record updated
DBUG_RETURN
(
0
);
end:
close_thread_tables
(
thd
);
DBUG_RETURN
(
error
);
}
}
...
@@ -2620,18 +2669,59 @@ void grant_free(void)
...
@@ -2620,18 +2669,59 @@ void grant_free(void)
}
}
/* Init grant array if possible */
/*
Initialize structures responsible for table/column-level privilege checking
and load information for them from tables in the 'mysql' database.
my_bool
grant_init
(
THD
*
org_thd
)
SYNOPSIS
grant_init()
RETURN VALUES
0 ok
1 Could not initialize grant's
*/
my_bool
grant_init
()
{
{
THD
*
thd
;
THD
*
thd
;
TABLE_LIST
tables
[
2
];
my_bool
return_val
;
MYSQL_LOCK
*
lock
;
DBUG_ENTER
(
"grant_init"
);
if
(
!
(
thd
=
new
THD
))
DBUG_RETURN
(
1
);
/* purecov: deadcode */
thd
->
store_globals
();
return_val
=
grant_reload
(
thd
);
delete
thd
;
/* Remember that we don't have a THD */
my_pthread_setspecific_ptr
(
THR_THD
,
0
);
DBUG_RETURN
(
return_val
);
}
/*
Initialize structures responsible for table/column-level privilege
checking and load information about grants from open privilege tables.
SYNOPSIS
grant_load()
thd Current thread
tables List containing open "mysql.tables_priv" and
"mysql.columns_priv" tables.
RETURN VALUES
FALSE - success
TRUE - error
*/
static
my_bool
grant_load
(
TABLE_LIST
*
tables
)
{
MEM_ROOT
*
memex_ptr
;
MEM_ROOT
*
memex_ptr
;
my_bool
return_val
=
1
;
my_bool
return_val
=
1
;
TABLE
*
t_table
,
*
c_table
;
TABLE
*
t_table
,
*
c_table
;
bool
check_no_resolve
=
specialflag
&
SPECIAL_NO_RESOLVE
;
bool
check_no_resolve
=
specialflag
&
SPECIAL_NO_RESOLVE
;
DBUG_ENTER
(
"grant_init"
);
MEM_ROOT
**
save_mem_root_ptr
=
my_pthread_getspecific_ptr
(
MEM_ROOT
**
,
THR_MALLOC
);
DBUG_ENTER
(
"grant_load"
);
grant_option
=
FALSE
;
grant_option
=
FALSE
;
(
void
)
hash_init
(
&
column_priv_hash
,
&
my_charset_latin1
,
(
void
)
hash_init
(
&
column_priv_hash
,
&
my_charset_latin1
,
...
@@ -2639,32 +2729,6 @@ my_bool grant_init(THD *org_thd)
...
@@ -2639,32 +2729,6 @@ my_bool grant_init(THD *org_thd)
(
hash_free_key
)
free_grant_table
,
0
);
(
hash_free_key
)
free_grant_table
,
0
);
init_sql_alloc
(
&
memex
,
ACL_ALLOC_BLOCK_SIZE
,
0
);
init_sql_alloc
(
&
memex
,
ACL_ALLOC_BLOCK_SIZE
,
0
);
/* Don't do anything if running with --skip-grant */
if
(
!
initialized
)
DBUG_RETURN
(
0
);
/* purecov: tested */
if
(
!
(
thd
=
new
THD
))
DBUG_RETURN
(
1
);
/* purecov: deadcode */
thd
->
store_globals
();
thd
->
db
=
my_strdup
(
"mysql"
,
MYF
(
0
));
thd
->
db_length
=
5
;
// Safety
bzero
((
char
*
)
&
tables
,
sizeof
(
tables
));
tables
[
0
].
alias
=
tables
[
0
].
real_name
=
(
char
*
)
"tables_priv"
;
tables
[
1
].
alias
=
tables
[
1
].
real_name
=
(
char
*
)
"columns_priv"
;
tables
[
0
].
next
=
tables
+
1
;
tables
[
0
].
lock_type
=
tables
[
1
].
lock_type
=
TL_READ
;
tables
[
0
].
db
=
tables
[
1
].
db
=
thd
->
db
;
uint
counter
;
if
(
open_tables
(
thd
,
tables
,
&
counter
))
goto
end
;
TABLE
*
ptr
[
2
];
// Lock tables for quick update
ptr
[
0
]
=
tables
[
0
].
table
;
ptr
[
1
]
=
tables
[
1
].
table
;
if
(
!
(
lock
=
mysql_lock_tables
(
thd
,
ptr
,
2
,
0
)))
goto
end
;
t_table
=
tables
[
0
].
table
;
c_table
=
tables
[
1
].
table
;
t_table
=
tables
[
0
].
table
;
c_table
=
tables
[
1
].
table
;
t_table
->
file
->
ha_index_init
(
0
);
t_table
->
file
->
ha_index_init
(
0
);
if
(
t_table
->
file
->
index_first
(
t_table
->
record
[
0
]))
if
(
t_table
->
file
->
index_first
(
t_table
->
record
[
0
]))
...
@@ -2674,7 +2738,6 @@ my_bool grant_init(THD *org_thd)
...
@@ -2674,7 +2738,6 @@ my_bool grant_init(THD *org_thd)
}
}
grant_option
=
TRUE
;
grant_option
=
TRUE
;
/* Will be restored by org_thd->store_globals() */
memex_ptr
=
&
memex
;
memex_ptr
=
&
memex
;
my_pthread_setspecific_ptr
(
THR_MALLOC
,
&
memex_ptr
);
my_pthread_setspecific_ptr
(
THR_MALLOC
,
&
memex_ptr
);
do
do
...
@@ -2711,48 +2774,63 @@ my_bool grant_init(THD *org_thd)
...
@@ -2711,48 +2774,63 @@ my_bool grant_init(THD *org_thd)
end_unlock:
end_unlock:
t_table
->
file
->
ha_index_end
();
t_table
->
file
->
ha_index_end
();
mysql_unlock_tables
(
thd
,
lock
);
my_pthread_setspecific_ptr
(
THR_MALLOC
,
save_mem_root_ptr
);
thd
->
version
--
;
// Force close to free memory
end:
close_thread_tables
(
thd
);
delete
thd
;
if
(
org_thd
)
org_thd
->
store_globals
();
else
{
/* Remember that we don't have a THD */
my_pthread_setspecific_ptr
(
THR_THD
,
0
);
}
DBUG_RETURN
(
return_val
);
DBUG_RETURN
(
return_val
);
}
}
/*
/*
Reload grant array (table and column privileges) if possible
Reload information about table and column level privileges if possible.
SYNOPSIS
SYNOPSIS
grant_reload()
grant_reload()
thd Thread handler (can be NULL)
thd Current thread
NOTES
NOTES
Locked tables are checked by acl_init and doesn't have to be checked here
Locked tables are checked by acl_reload() and doesn't have to be checked
in this call.
This function is also used for initialization of structures responsible
for table/column-level privilege checking.
RETURN VALUE
FALSE Success
TRUE Error
*/
*/
void
grant_reload
(
THD
*
thd
)
my_bool
grant_reload
(
THD
*
thd
)
{
{
TABLE_LIST
tables
[
2
];
HASH
old_column_priv_hash
;
HASH
old_column_priv_hash
;
bool
old_grant_option
;
bool
old_grant_option
;
MEM_ROOT
old_mem
;
MEM_ROOT
old_mem
;
my_bool
return_val
=
1
;
DBUG_ENTER
(
"grant_reload"
);
DBUG_ENTER
(
"grant_reload"
);
/* Don't do anything if running with --skip-grant-tables */
if
(
!
initialized
)
DBUG_RETURN
(
0
);
bzero
((
char
*
)
tables
,
sizeof
(
tables
));
tables
[
0
].
alias
=
tables
[
0
].
real_name
=
(
char
*
)
"tables_priv"
;
tables
[
1
].
alias
=
tables
[
1
].
real_name
=
(
char
*
)
"columns_priv"
;
tables
[
0
].
db
=
tables
[
1
].
db
=
(
char
*
)
"mysql"
;
tables
[
0
].
next
=
tables
+
1
;
tables
[
0
].
lock_type
=
tables
[
1
].
lock_type
=
TL_READ
;
/*
To avoid deadlocks we should obtain table locks before
obtaining LOCK_grant rwlock.
*/
if
(
simple_open_n_lock_tables
(
thd
,
tables
))
goto
end
;
rw_wrlock
(
&
LOCK_grant
);
rw_wrlock
(
&
LOCK_grant
);
grant_version
++
;
grant_version
++
;
old_column_priv_hash
=
column_priv_hash
;
old_column_priv_hash
=
column_priv_hash
;
old_grant_option
=
grant_option
;
old_grant_option
=
grant_option
;
old_mem
=
memex
;
old_mem
=
memex
;
if
(
grant_init
(
thd
))
if
(
(
return_val
=
grant_load
(
tables
)
))
{
// Error. Revert to old hash
{
// Error. Revert to old hash
DBUG_PRINT
(
"error"
,(
"Reverting to old privileges"
));
DBUG_PRINT
(
"error"
,(
"Reverting to old privileges"
));
grant_free
();
/* purecov: deadcode */
grant_free
();
/* purecov: deadcode */
...
@@ -2766,7 +2844,9 @@ void grant_reload(THD *thd)
...
@@ -2766,7 +2844,9 @@ void grant_reload(THD *thd)
free_root
(
&
old_mem
,
MYF
(
0
));
free_root
(
&
old_mem
,
MYF
(
0
));
}
}
rw_unlock
(
&
LOCK_grant
);
rw_unlock
(
&
LOCK_grant
);
DBUG_VOID_RETURN
;
end:
close_thread_tables
(
thd
);
DBUG_RETURN
(
return_val
);
}
}
...
...
sql/sql_acl.h
View file @
0683c122
...
@@ -134,8 +134,8 @@ class ACL_DB :public ACL_ACCESS
...
@@ -134,8 +134,8 @@ class ACL_DB :public ACL_ACCESS
/* prototypes */
/* prototypes */
bool
hostname_requires_resolving
(
const
char
*
hostname
);
bool
hostname_requires_resolving
(
const
char
*
hostname
);
my_bool
acl_init
(
THD
*
thd
,
bool
dont_read_acl_tables
);
my_bool
acl_init
(
bool
dont_read_acl_tables
);
void
acl_reload
(
THD
*
thd
);
my_bool
acl_reload
(
THD
*
thd
);
void
acl_free
(
bool
end
=
0
);
void
acl_free
(
bool
end
=
0
);
ulong
acl_get
(
const
char
*
host
,
const
char
*
ip
,
ulong
acl_get
(
const
char
*
host
,
const
char
*
ip
,
const
char
*
user
,
const
char
*
db
,
my_bool
db_is_pattern
);
const
char
*
user
,
const
char
*
db
,
my_bool
db_is_pattern
);
...
@@ -151,9 +151,9 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &user_list,
...
@@ -151,9 +151,9 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &user_list,
int
mysql_table_grant
(
THD
*
thd
,
TABLE_LIST
*
table
,
List
<
LEX_USER
>
&
user_list
,
int
mysql_table_grant
(
THD
*
thd
,
TABLE_LIST
*
table
,
List
<
LEX_USER
>
&
user_list
,
List
<
LEX_COLUMN
>
&
column_list
,
ulong
rights
,
List
<
LEX_COLUMN
>
&
column_list
,
ulong
rights
,
bool
revoke
);
bool
revoke
);
my_bool
grant_init
(
THD
*
thd
);
my_bool
grant_init
();
void
grant_free
(
void
);
void
grant_free
(
void
);
void
grant_reload
(
THD
*
thd
);
my_bool
grant_reload
(
THD
*
thd
);
bool
check_grant
(
THD
*
thd
,
ulong
want_access
,
TABLE_LIST
*
tables
,
bool
check_grant
(
THD
*
thd
,
ulong
want_access
,
TABLE_LIST
*
tables
,
uint
show_command
,
uint
number
,
bool
dont_print_error
);
uint
show_command
,
uint
number
,
bool
dont_print_error
);
bool
check_grant_column
(
THD
*
thd
,
TABLE
*
table
,
const
char
*
name
,
uint
length
,
bool
check_grant_column
(
THD
*
thd
,
TABLE
*
table
,
const
char
*
name
,
uint
length
,
...
...
sql/sql_parse.cc
View file @
0683c122
...
@@ -4988,10 +4988,27 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
...
@@ -4988,10 +4988,27 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
#ifndef NO_EMBEDDED_ACCESS_CHECKS
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if
(
options
&
REFRESH_GRANT
)
if
(
options
&
REFRESH_GRANT
)
{
{
acl_reload
(
thd
);
THD
*
tmp_thd
=
0
;
grant_reload
(
thd
);
/*
if
(
mqh_used
)
If reload_acl_and_cache() is called from SIGHUP handler we have to
reset_mqh
(
thd
,(
LEX_USER
*
)
NULL
,
TRUE
);
allocate temporary THD for execution of acl_reload()/grant_reload().
*/
if
(
!
thd
&&
(
thd
=
(
tmp_thd
=
new
THD
)))
thd
->
store_globals
();
if
(
thd
)
{
(
void
)
acl_reload
(
thd
);
(
void
)
grant_reload
(
thd
);
if
(
mqh_used
)
reset_mqh
(
thd
,
(
LEX_USER
*
)
NULL
,
TRUE
);
}
if
(
tmp_thd
)
{
delete
tmp_thd
;
/* Remember that we don't have a THD */
my_pthread_setspecific_ptr
(
THR_THD
,
0
);
thd
=
0
;
}
}
}
#endif
#endif
if
(
options
&
REFRESH_LOG
)
if
(
options
&
REFRESH_LOG
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment