Commit 64b27c73 authored by Vicentiu Ciorbaru's avatar Vicentiu Ciorbaru Committed by Sergei Golubchik

Added default role implementation

parent 43351faf
...@@ -1202,13 +1202,13 @@ SET @aux= "SELECT COUNT(*) ...@@ -1202,13 +1202,13 @@ SET @aux= "SELECT COUNT(*)
prepare my_stmt from @aux; prepare my_stmt from @aux;
execute my_stmt; execute my_stmt;
COUNT(*) COUNT(*)
44 45
execute my_stmt; execute my_stmt;
COUNT(*) COUNT(*)
44 45
execute my_stmt; execute my_stmt;
COUNT(*) COUNT(*)
44 45
deallocate prepare my_stmt; deallocate prepare my_stmt;
drop procedure if exists p1| drop procedure if exists p1|
drop table if exists t1| drop table if exists t1|
......
use mysql; use mysql;
alter table user drop column is_role; alter table user drop column is_role;
alter table user drop column default_role;
flush privileges; flush privileges;
create role test_role; create role test_role;
ERROR HY000: Column count of mysql.user is wrong. Expected 44, found 43. Created with MariaDB MYSQL_VERSION_ID, now running MYSQL_VERSION_ID. Please use mysql_upgrade to fix this error. ERROR HY000: Column count of mysql.user is wrong. Expected 44, found 43. Created with MariaDB MYSQL_VERSION_ID, now running MYSQL_VERSION_ID. Please use mysql_upgrade to fix this error.
...@@ -8,6 +9,9 @@ ERROR HY000: Operation DROP ROLE failed for 'test_role' ...@@ -8,6 +9,9 @@ ERROR HY000: Operation DROP ROLE failed for 'test_role'
alter table user add column is_role enum('N', 'Y') default 'N' not null alter table user add column is_role enum('N', 'Y') default 'N' not null
COLLATE utf8_general_ci COLLATE utf8_general_ci
after password_expired; after password_expired;
alter table user add column default_role char(80) binary default '' not null
COLLATE utf8_general_ci
after is_role;
update user set is_role='N'; update user set is_role='N';
flush privileges; flush privileges;
create role test_role; create role test_role;
......
...@@ -4,6 +4,7 @@ connect (mysql, localhost, root,,); ...@@ -4,6 +4,7 @@ connect (mysql, localhost, root,,);
use mysql; use mysql;
alter table user drop column is_role; alter table user drop column is_role;
alter table user drop column default_role;
flush privileges; flush privileges;
...@@ -15,12 +16,12 @@ drop role test_role; ...@@ -15,12 +16,12 @@ drop role test_role;
alter table user add column is_role enum('N', 'Y') default 'N' not null alter table user add column is_role enum('N', 'Y') default 'N' not null
COLLATE utf8_general_ci COLLATE utf8_general_ci
after password_expired; after password_expired;
alter table user add column default_role char(80) binary default '' not null
COLLATE utf8_general_ci
after is_role;
update user set is_role='N'; update user set is_role='N';
flush privileges; flush privileges;
create role test_role; create role test_role;
drop role test_role; drop role test_role;
create user test_user@localhost;
create role test_role;
grant select on *.* to test_role;
grant test_role to test_user@localhost;
show grants;
Grants for test_user@localhost
GRANT test_role TO 'test_user'@'localhost'
GRANT USAGE ON *.* TO 'test_user'@'localhost'
set default role test_role;
select user, host, default_role from mysql.user;
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'user'
select user, host, default_role from mysql.user where user='test_user';
user host default_role
test_user localhost test_role
show grants;
Grants for test_user@localhost
GRANT test_role TO 'test_user'@'localhost'
GRANT USAGE ON *.* TO 'test_user'@'localhost'
GRANT SELECT ON *.* TO 'test_role'
select user, host, default_role from mysql.user where user='test_user';
user host default_role
test_user localhost test_role
set default role NONE;
select user, host, default_role from mysql.user where user='test_user';
user host default_role
test_user localhost
set default role invalid_role;
ERROR OP000: Invalid role specification `invalid_role`.
select user, host, default_role from mysql.user where user='test_user';
user host default_role
test_user localhost
select user, host, default_role from mysql.user;
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'user'
drop role test_role;
drop user test_user@localhost;
source include/not_embedded.inc;
# This test checks clearing a default role from a user.
# Create a user with no privileges
create user test_user@localhost;
create role test_role;
grant select on *.* to test_role;
grant test_role to test_user@localhost;
change_user 'test_user';
show grants;
set default role test_role;
# Even though a user has the default role set, without reconnecting, we should
# not already have the roles privileges.
--error ER_TABLEACCESS_DENIED_ERROR
select user, host, default_role from mysql.user;
change_user 'root';
select user, host, default_role from mysql.user where user='test_user';
change_user 'test_user';
# This should show that the new test_user has the role's grants enabled.
show grants;
select user, host, default_role from mysql.user where user='test_user';
set default role NONE;
# We should still have the role set right now.
select user, host, default_role from mysql.user where user='test_user';
# Make sure we do not somehow get privileges to set an invalid role
--error ER_INVALID_ROLE
set default role invalid_role;
change_user 'root';
select user, host, default_role from mysql.user where user='test_user';
change_user 'test_user';
# The user does not have a default role set anymore. Make sure we don't still
# get the privileges.
--error ER_TABLEACCESS_DENIED_ERROR
select user, host, default_role from mysql.user;
change_user 'root';
# Cleanup
drop role test_role;
drop user test_user@localhost;
create user user_a@localhost;
create user user_b@localhost;
create role role_a;
create role role_b;
grant role_a to user_a@localhost;
grant role_b to user_b@localhost;
grant role_a to user_a@localhost;
grant select on *.* to role_a;
grant role_b to user_b@localhost;
grant insert, update on *.* to role_b;
set default role role_a for user_b@localhost;
ERROR 42000: Access denied for user 'user_a'@'localhost' to database 'mysql'
set default role role_a for user_a@localhost;
set default role invalid_role for user_a@localhost;
ERROR OP000: Invalid role specification `invalid_role`.
set default role role_b for user_a@localhost;
ERROR OP000: Invalid role specification `role_b`.
set default role role_b for user_b@localhost;
show grants;
Grants for user_a@localhost
GRANT role_a TO 'user_a'@'localhost'
GRANT USAGE ON *.* TO 'user_a'@'localhost'
GRANT SELECT ON *.* TO 'role_a'
select user, host, default_role from mysql.user where user like 'user_%';
user host default_role
user_a localhost role_a
user_b localhost role_b
set default role NONE for current_user;
select user, host, default_role from mysql.user where user like 'user_%';
user host default_role
user_a localhost
user_b localhost role_b
set default role current_role for current_user;
select user, host, default_role from mysql.user where user like 'user_%';
user host default_role
user_a localhost role_a
user_b localhost role_b
set default role role_b for current_user;
ERROR OP000: Invalid role specification `role_b`.
show grants;
Grants for user_b@localhost
GRANT role_b TO 'user_b'@'localhost'
GRANT USAGE ON *.* TO 'user_b'@'localhost'
GRANT INSERT, UPDATE ON *.* TO 'role_b'
select user, host, default_role from mysql.user where user like 'user_%';
ERROR 42000: SELECT command denied to user 'user_b'@'localhost' for table 'user'
insert into mysql.user (user, host) values ('someuser', 'somehost');
Warnings:
Warning 1364 Field 'ssl_cipher' doesn't have a default value
Warning 1364 Field 'x509_issuer' doesn't have a default value
Warning 1364 Field 'x509_subject' doesn't have a default value
Warning 1364 Field 'authentication_string' doesn't have a default value
set default role NONE for user_a@localhost;
show grants;
Grants for user_a@localhost
GRANT role_a TO 'user_a'@'localhost'
GRANT USAGE ON *.* TO 'user_a'@'localhost'
GRANT INSERT, UPDATE ON *.* TO 'role_b'
select user, host, default_role from mysql.user where user like 'user_%';
ERROR 42000: SELECT command denied to user 'user_a'@'localhost' for table 'user'
drop role role_a;
drop role role_b;
drop user someuser@somehost;
drop user user_a@localhost;
drop user user_b@localhost;
source include/not_embedded.inc;
# This test checks setting a default role to a different user;
create user user_a@localhost;
create user user_b@localhost;
create role role_a;
create role role_b;
grant role_a to user_a@localhost;
grant role_b to user_b@localhost;
grant role_a to user_a@localhost;
grant select on *.* to role_a;
grant role_b to user_b@localhost;
grant insert, update on *.* to role_b;
change_user 'user_a';
# A user should not be a able to set a default role for someone else,
# if he hasn't got write access to the database.
--error ER_DBACCESS_DENIED_ERROR
set default role role_a for user_b@localhost;
# Should have the same effect as set default role role_a.
set default role role_a for user_a@localhost;
change_user 'root';
# Not even a 'root' user should be able to set an invalid role for a user.
--error ER_INVALID_ROLE
set default role invalid_role for user_a@localhost;
--error ER_INVALID_ROLE
set default role role_b for user_a@localhost;
# Make sure we can set a default role for a different user than the one that
# is actually running the command.
set default role role_b for user_b@localhost;
change_user 'user_a';
show grants;
select user, host, default_role from mysql.user where user like 'user_%';
set default role NONE for current_user;
select user, host, default_role from mysql.user where user like 'user_%';
set default role current_role for current_user;
select user, host, default_role from mysql.user where user like 'user_%';
# Make sure we can't set a default role not granted to us, using current_user
--error ER_INVALID_ROLE
set default role role_b for current_user;
change_user 'user_b';
show grants;
--error ER_TABLEACCESS_DENIED_ERROR
select user, host, default_role from mysql.user where user like 'user_%';
# Make sure the default role setting worked from root.
insert into mysql.user (user, host) values ('someuser', 'somehost');
# Since we have update privileges on the mysql.user table, we should
# be able to set a default role for a different user.
set default role NONE for user_a@localhost;
change_user 'user_a';
# There is no default role set any more.
show grants;
--error ER_TABLEACCESS_DENIED_ERROR
select user, host, default_role from mysql.user where user like 'user_%';
change_user 'root';
drop role role_a;
drop role role_b;
drop user someuser@somehost;
drop user user_a@localhost;
drop user user_b@localhost;
create user test_user@localhost;
create role test_role;
create role not_granted_role;
grant select on *.* to test_role;
grant test_role to test_user@localhost;
show grants;
Grants for test_user@localhost
GRANT test_role TO 'test_user'@'localhost'
GRANT USAGE ON *.* TO 'test_user'@'localhost'
select user, host, default_role from mysql.user;
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'user'
set default role invalid_role;
ERROR OP000: Invalid role specification `invalid_role`.
set default role not_granted_role;
ERROR OP000: Invalid role specification `not_granted_role`.
set default role test_role;
select user, host, default_role from mysql.user;
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'user'
select user, host, default_role from mysql.user where user='test_user';
user host default_role
test_user localhost test_role
show grants;
Grants for test_user@localhost
GRANT test_role TO 'test_user'@'localhost'
GRANT USAGE ON *.* TO 'test_user'@'localhost'
GRANT SELECT ON *.* TO 'test_role'
select user, host, default_role from mysql.user where user='test_user';
user host default_role
test_user localhost test_role
set default role invalid_role;
ERROR OP000: Invalid role specification `invalid_role`.
select user, host, default_role from mysql.user where user='test_user';
user host default_role
test_user localhost test_role
revoke test_role from test_user@localhost;
select user, host, default_role from mysql.user where user='test_user';
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'user'
drop role test_role;
drop role not_granted_role;
drop user test_user@localhost;
source include/not_embedded.inc;
# This test checks the error paths possible during set default role.
# Create a user with no privileges
create user test_user@localhost;
create role test_role;
create role not_granted_role;
grant select on *.* to test_role;
grant test_role to test_user@localhost;
change_user 'test_user';
show grants;
--error ER_TABLEACCESS_DENIED_ERROR
select user, host, default_role from mysql.user;
# A user can not set a default role that does not exist in the database.
--error ER_INVALID_ROLE
set default role invalid_role;
# A user can not set a default role if he can not call set role <role>.
--error ER_INVALID_ROLE
set default role not_granted_role;
set default role test_role;
# Even though a user has the default role set, without reconnecting, we should
# not already have the roles privileges.
--error ER_TABLEACCESS_DENIED_ERROR
select user, host, default_role from mysql.user;
change_user 'root';
select user, host, default_role from mysql.user where user='test_user';
change_user 'test_user';
# This should show that the new test_user has the role's grants enabled.
show grants;
select user, host, default_role from mysql.user where user='test_user';
# If we have a failed set default role attempt, don't change the already set
# default role.
--error ER_INVALID_ROLE
set default role invalid_role;
select user, host, default_role from mysql.user where user='test_user';
change_user 'root';
# Now, even though a default role is still set for test_user, make sure the
# user does not get the rights, if he can not set the role.
revoke test_role from test_user@localhost;
change_user 'test_user';
--error ER_TABLEACCESS_DENIED_ERROR
select user, host, default_role from mysql.user where user='test_user';
change_user 'root';
# Cleanup
drop role test_role;
drop role not_granted_role;
drop user test_user@localhost;
create user test_user@localhost;
create role test_role;
grant select on *.* to test_role;
grant test_role to test_user@localhost;
show grants;
Grants for test_user@localhost
GRANT test_role TO 'test_user'@'localhost'
GRANT USAGE ON *.* TO 'test_user'@'localhost'
select user, host, default_role from mysql.user where user = 'test_user';
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'user'
set default role test_role;
select user, host, default_role from mysql.user where user = 'test_user';
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'user'
select user, host, default_role from mysql.user where user = 'test_user';
user host default_role
test_user localhost test_role
show grants;
Grants for test_user@localhost
GRANT test_role TO 'test_user'@'localhost'
GRANT USAGE ON *.* TO 'test_user'@'localhost'
GRANT SELECT ON *.* TO 'test_role'
select user, host, default_role from mysql.user where user = 'test_user';
user host default_role
test_user localhost test_role
set default role NONE;
select user, host, default_role from mysql.user where user = 'test_user';
user host default_role
test_user localhost
show grants;
Grants for test_user@localhost
GRANT test_role TO 'test_user'@'localhost'
GRANT USAGE ON *.* TO 'test_user'@'localhost'
select user, host, default_role from mysql.user where user = 'test_user';
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'user'
select user, host, default_role from mysql.user where user = 'test_user';
user host default_role
test_user localhost
set default role test_role for test_user@localhost;
show grants;
Grants for test_user@localhost
GRANT test_role TO 'test_user'@'localhost'
GRANT USAGE ON *.* TO 'test_user'@'localhost'
GRANT SELECT ON *.* TO 'test_role'
select user, host, default_role from mysql.user where user = 'test_user';
user host default_role
test_user localhost test_role
drop role test_role;
drop user test_user@localhost;
source include/not_embedded.inc;
create user test_user@localhost;
create role test_role;
grant select on *.* to test_role;
grant test_role to test_user@localhost;
--connect (c1, localhost, test_user,,)
show grants;
--error ER_TABLEACCESS_DENIED_ERROR
select user, host, default_role from mysql.user where user = 'test_user';
set default role test_role;
--error ER_TABLEACCESS_DENIED_ERROR
select user, host, default_role from mysql.user where user = 'test_user';
disconnect c1;
connection default;
select user, host, default_role from mysql.user where user = 'test_user';
--connect (c1, localhost, test_user,,)
show grants;
select user, host, default_role from mysql.user where user = 'test_user';
set default role NONE;
disconnect c1;
connection default;
select user, host, default_role from mysql.user where user = 'test_user';
--connect (c1, localhost, test_user,,)
show grants;
--error ER_TABLEACCESS_DENIED_ERROR
select user, host, default_role from mysql.user where user = 'test_user';
disconnect c1;
connection default;
select user, host, default_role from mysql.user where user = 'test_user';
set default role test_role for test_user@localhost;
--connect (c1, localhost, test_user,,)
show grants;
select user, host, default_role from mysql.user where user = 'test_user';
disconnect c1;
connection default;
drop role test_role;
drop user test_user@localhost;
...@@ -16,10 +16,10 @@ Host User Role Admin_option ...@@ -16,10 +16,10 @@ Host User Role Admin_option
test_role1 test_role2 N test_role1 test_role2 N
grant select on *.* to test_role2; grant select on *.* to test_role2;
select * from mysql.user where user like 'test_role1'; select * from mysql.user where user like 'test_role1';
Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role
test_role1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y test_role1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y
select * from mysql.user where user like 'test_role2'; select * from mysql.user where user like 'test_role2';
Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role
test_role2 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y test_role2 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y
select * from mysql.roles_mapping; select * from mysql.roles_mapping;
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'roles_mapping' ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'roles_mapping'
......
...@@ -11,7 +11,7 @@ localhost root test_role1 Y ...@@ -11,7 +11,7 @@ localhost root test_role1 Y
localhost test_user test_role1 N localhost test_user test_role1 N
grant select on *.* to test_role1; grant select on *.* to test_role1;
select * from mysql.user where user='test_role1'; select * from mysql.user where user='test_role1';
Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role
test_role1 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y test_role1 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y
select * from mysql.roles_mapping; select * from mysql.roles_mapping;
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'roles_mapping' ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'roles_mapping'
......
...@@ -852,6 +852,7 @@ int set_var_password::update(THD *thd) ...@@ -852,6 +852,7 @@ int set_var_password::update(THD *thd)
/***************************************************************************** /*****************************************************************************
Functions to handle SET ROLE Functions to handle SET ROLE
*****************************************************************************/ *****************************************************************************/
int set_var_role::check(THD *thd) int set_var_role::check(THD *thd)
{ {
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
...@@ -871,6 +872,29 @@ int set_var_role::update(THD *thd) ...@@ -871,6 +872,29 @@ int set_var_role::update(THD *thd)
#endif #endif
} }
/*****************************************************************************
Functions to handle SET DEFAULT ROLE
*****************************************************************************/
int set_var_default_role::check(THD *thd)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
user= get_current_user(thd, user);
int status= acl_check_set_default_role(thd, user->host.str, user->user.str);
return status;
#else
return 0;
#endif
}
int set_var_default_role::update(THD *thd)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
return acl_set_default_role(thd, user->host.str, user->user.str, role.str);
#else
return 0;
#endif
}
/***************************************************************************** /*****************************************************************************
Functions to handle SET NAMES and SET CHARACTER SET Functions to handle SET NAMES and SET CHARACTER SET
......
...@@ -291,6 +291,18 @@ class set_var_role: public set_var_base ...@@ -291,6 +291,18 @@ class set_var_role: public set_var_base
int update(THD *thd); int update(THD *thd);
}; };
/* For SET DEFAULT ROLE */
class set_var_default_role: public set_var_base
{
LEX_USER *user;
LEX_STRING role;
public:
set_var_default_role(LEX_USER *user_arg, LEX_STRING role_arg) :
user(user_arg), role(role_arg) {}
int check(THD *thd);
int update(THD *thd);
};
/* For SET NAMES and SET CHARACTER SET */ /* For SET NAMES and SET CHARACTER SET */
......
...@@ -2936,7 +2936,7 @@ ER_PASSWORD_ANONYMOUS_USER 42000 ...@@ -2936,7 +2936,7 @@ ER_PASSWORD_ANONYMOUS_USER 42000
cze "Používáte MySQL jako anonymní uživatel a anonymní uživatelé nemají povoleno měnit hesla" cze "Používáte MySQL jako anonymní uživatel a anonymní uživatelé nemají povoleno měnit hesla"
dan "Du bruger MariaDB som anonym bruger. Anonyme brugere må ikke ændre adgangskoder" dan "Du bruger MariaDB som anonym bruger. Anonyme brugere må ikke ændre adgangskoder"
nla "U gebruikt MariaDB als anonieme gebruiker en deze mogen geen wachtwoorden wijzigen" nla "U gebruikt MariaDB als anonieme gebruiker en deze mogen geen wachtwoorden wijzigen"
eng "You are using MariaDB as an anonymous user and anonymous users are not allowed to change passwords" eng "You are using MariaDB as an anonymous user and anonymous users are not allowed to modify user settings"
est "Te kasutate MariaDB-i anonüümse kasutajana, kelledel pole parooli muutmise õigust" est "Te kasutate MariaDB-i anonüümse kasutajana, kelledel pole parooli muutmise õigust"
fre "Vous utilisez un utilisateur anonyme et les utilisateurs anonymes ne sont pas autorisés à changer les mots de passe" fre "Vous utilisez un utilisateur anonyme et les utilisateurs anonymes ne sont pas autorisés à changer les mots de passe"
ger "Sie benutzen MariaDB als anonymer Benutzer und dürfen daher keine Passwörter ändern" ger "Sie benutzen MariaDB als anonymer Benutzer und dürfen daher keine Passwörter ändern"
...@@ -2946,7 +2946,7 @@ ER_PASSWORD_ANONYMOUS_USER 42000 ...@@ -2946,7 +2946,7 @@ ER_PASSWORD_ANONYMOUS_USER 42000
jpn "MySQL を匿名ユーザーで使用しているので、パスワードの変更はできません。" jpn "MySQL を匿名ユーザーで使用しているので、パスワードの変更はできません。"
kor "당신은 MariaDB서버에 익명의 사용자로 접속을 하셨습니다.익명의 사용자는 암호를 변경할 수 없습니다." kor "당신은 MariaDB서버에 익명의 사용자로 접속을 하셨습니다.익명의 사용자는 암호를 변경할 수 없습니다."
por "Você está usando o MariaDB como usuário anônimo e usuários anônimos não têm permissão para mudar senhas" por "Você está usando o MariaDB como usuário anônimo e usuários anônimos não têm permissão para mudar senhas"
rum "Dumneavoastra folositi MariaDB ca un utilizator anonim si utilizatorii anonimi nu au voie sa schimbe parolele" rum "Dumneavoastra folositi MariaDB ca un utilizator anonim si utilizatorii anonimi nu au voie sa schimbe setarile utilizatorilor."
rus "Вы используете MariaDB от имени анонимного пользователя, а анонимным пользователям не разрешается менять пароли" rus "Вы используете MariaDB от имени анонимного пользователя, а анонимным пользователям не разрешается менять пароли"
serbian "Vi koristite MariaDB kao anonimni korisnik a anonimnim korisnicima nije dozvoljeno da menjaju lozinke" serbian "Vi koristite MariaDB kao anonimni korisnik a anonimnim korisnicima nije dozvoljeno da menjaju lozinke"
spa "Tu estás usando MariaDB como un usuario anonimo y usuarios anonimos no tienen permiso para cambiar las claves" spa "Tu estás usando MariaDB como un usuario anonimo y usuarios anonimos no tienen permiso para cambiar las claves"
...@@ -7110,9 +7110,3 @@ ER_IT_IS_A_VIEW 42S02 ...@@ -7110,9 +7110,3 @@ ER_IT_IS_A_VIEW 42S02
eng "'%-.192s' is a view" eng "'%-.192s' is a view"
ER_SLAVE_SKIP_NOT_IN_GTID ER_SLAVE_SKIP_NOT_IN_GTID
eng "When using GTID, @@sql_slave_skip_counter can not be used. Instead, setting @@gtid_slave_pos explicitly can be used to skip to after a given GTID position." eng "When using GTID, @@sql_slave_skip_counter can not be used. Instead, setting @@gtid_slave_pos explicitly can be used to skip to after a given GTID position."
ER_DEFAULT_ROLE_ANONYMOUS_USER
eng "You are using MariaDB as an anonymous user and anonymous users are not allowed to change default roles."
rum "Dumneavoastra folositi MariaDB ca un utilizator anonim si utilizatorii anonimi nu au voie sa schimbe rolurile implicite."
ER_NO_SUCH_ROLE
eng "The role specified '%-.64s' does not exist."
rum "Rolul specificat '%-.64s' nu există."
...@@ -265,6 +265,7 @@ class ACL_USER :public ACL_USER_BASE ...@@ -265,6 +265,7 @@ class ACL_USER :public ACL_USER_BASE
const char *ssl_cipher, *x509_issuer, *x509_subject; const char *ssl_cipher, *x509_issuer, *x509_subject;
LEX_STRING plugin; LEX_STRING plugin;
LEX_STRING auth_string; LEX_STRING auth_string;
LEX_STRING default_rolename;
ACL_USER *copy(MEM_ROOT *root) ACL_USER *copy(MEM_ROOT *root)
{ {
...@@ -284,6 +285,8 @@ class ACL_USER :public ACL_USER_BASE ...@@ -284,6 +285,8 @@ class ACL_USER :public ACL_USER_BASE
dst->plugin.str= strmake_root(root, plugin.str, plugin.length); dst->plugin.str= strmake_root(root, plugin.str, plugin.length);
dst->auth_string.str= safe_strdup_root(root, auth_string.str); dst->auth_string.str= safe_strdup_root(root, auth_string.str);
dst->host.hostname= safe_strdup_root(root, host.hostname); dst->host.hostname= safe_strdup_root(root, host.hostname);
dst->default_rolename.str= safe_strdup_root(root, default_rolename.str);
dst->default_rolename.length= default_rolename.length;
bzero(&dst->role_grants, sizeof(role_grants)); bzero(&dst->role_grants, sizeof(role_grants));
return dst; return dst;
} }
...@@ -702,6 +705,7 @@ bool ROLE_GRANT_PAIR::init(MEM_ROOT *mem, char *username, ...@@ -702,6 +705,7 @@ bool ROLE_GRANT_PAIR::init(MEM_ROOT *mem, char *username,
#define NORMAL_HANDSHAKE_SIZE 6 #define NORMAL_HANDSHAKE_SIZE 6
#define ROLE_ASSIGN_COLUMN_IDX 43 #define ROLE_ASSIGN_COLUMN_IDX 43
#define DEFAULT_ROLE_COLUMN_IDX 44
/* various flags valid for ACL_USER */ /* various flags valid for ACL_USER */
#define IS_ROLE (1L << 0) #define IS_ROLE (1L << 0)
/* Flag to mark that a ROLE is on the recursive DEPTH_FIRST_SEARCH stack */ /* Flag to mark that a ROLE is on the recursive DEPTH_FIRST_SEARCH stack */
...@@ -1347,6 +1351,14 @@ static bool acl_load(THD *thd, TABLE_LIST *tables) ...@@ -1347,6 +1351,14 @@ static bool acl_load(THD *thd, TABLE_LIST *tables)
(void) my_init_dynamic_array(&user.role_grants,sizeof(ACL_ROLE *), (void) my_init_dynamic_array(&user.role_grants,sizeof(ACL_ROLE *),
8, 8, MYF(0)); 8, 8, MYF(0));
/* check default role, if any */
if (!is_role && table->s->fields >= 45)
{
user.default_rolename.str= get_field(&acl_memroot, table->field[44]);
user.default_rolename.length= user.default_rolename.str ?
strlen(user.default_rolename.str) : 0;
}
if (is_role) if (is_role)
{ {
DBUG_PRINT("info", ("Found role %s", user.user.str)); DBUG_PRINT("info", ("Found role %s", user.user.str));
...@@ -1867,7 +1879,8 @@ bool acl_getroot(Security_context *sctx, char *user, char *host, ...@@ -1867,7 +1879,8 @@ bool acl_getroot(Security_context *sctx, char *user, char *host,
DBUG_RETURN(res); DBUG_RETURN(res);
} }
int acl_check_setrole(THD *thd, char *rolename, ulonglong *access) int check_user_can_set_role(const char *host, const char *user,
const char *rolename, ulonglong *access)
{ {
ACL_ROLE *role; ACL_ROLE *role;
ACL_USER_BASE *acl_user_base; ACL_USER_BASE *acl_user_base;
...@@ -1882,8 +1895,7 @@ int acl_check_setrole(THD *thd, char *rolename, ulonglong *access) ...@@ -1882,8 +1895,7 @@ int acl_check_setrole(THD *thd, char *rolename, ulonglong *access)
{ {
/* have to clear the privileges */ /* have to clear the privileges */
/* get the current user */ /* get the current user */
acl_user= find_user_exact(thd->security_ctx->priv_host, acl_user= find_user_exact(host, user);
thd->security_ctx->priv_user);
if (acl_user == NULL) if (acl_user == NULL)
{ {
my_error(ER_INVALID_CURRENT_USER, MYF(0), rolename); my_error(ER_INVALID_CURRENT_USER, MYF(0), rolename);
...@@ -1911,9 +1923,7 @@ int acl_check_setrole(THD *thd, char *rolename, ulonglong *access) ...@@ -1911,9 +1923,7 @@ int acl_check_setrole(THD *thd, char *rolename, ulonglong *access)
continue; continue;
acl_user= (ACL_USER *)acl_user_base; acl_user= (ACL_USER *)acl_user_base;
/* Yes! priv_user@host. Don't ask why - that's what check_access() does. */ if (acl_user->wild_eq(user, host))
if (acl_user->wild_eq(thd->security_ctx->priv_user,
thd->security_ctx->host))
{ {
is_granted= TRUE; is_granted= TRUE;
break; break;
...@@ -1935,6 +1945,15 @@ int acl_check_setrole(THD *thd, char *rolename, ulonglong *access) ...@@ -1935,6 +1945,15 @@ int acl_check_setrole(THD *thd, char *rolename, ulonglong *access)
end: end:
mysql_mutex_unlock(&acl_cache->lock); mysql_mutex_unlock(&acl_cache->lock);
return result; return result;
}
int acl_check_setrole(THD *thd, char *rolename, ulonglong *access)
{
/* Yes! priv_user@host. Don't ask why - that's what check_access() does. */
return check_user_can_set_role(thd->security_ctx->host,
thd->security_ctx->priv_user,
rolename, access);
} }
...@@ -1960,7 +1979,6 @@ int acl_setrole(THD *thd, char *rolename, ulonglong access) ...@@ -1960,7 +1979,6 @@ int acl_setrole(THD *thd, char *rolename, ulonglong access)
return 0; return 0;
} }
static uchar* check_get_key(ACL_USER *buff, size_t *length, static uchar* check_get_key(ACL_USER *buff, size_t *length,
my_bool not_used __attribute__((unused))) my_bool not_used __attribute__((unused)))
{ {
...@@ -2068,6 +2086,7 @@ static void acl_insert_user(const char *user, const char *host, ...@@ -2068,6 +2086,7 @@ static void acl_insert_user(const char *user, const char *host,
mysql_mutex_assert_owner(&acl_cache->lock); mysql_mutex_assert_owner(&acl_cache->lock);
bzero(&acl_user, sizeof(acl_user));
acl_user.user.str=*user ? strdup_root(&acl_memroot,user) : 0; acl_user.user.str=*user ? strdup_root(&acl_memroot,user) : 0;
acl_user.user.length= strlen(user); acl_user.user.length= strlen(user);
update_hostname(&acl_user.host, safe_strdup_root(&acl_memroot, host)); update_hostname(&acl_user.host, safe_strdup_root(&acl_memroot, host));
...@@ -2518,41 +2537,40 @@ bool acl_check_host(const char *host, const char *ip) ...@@ -2518,41 +2537,40 @@ bool acl_check_host(const char *host, const char *ip)
return 1; // Host is not allowed return 1; // Host is not allowed
} }
/** /**
Check if the user is allowed to change password Check if the user is allowed to alter the mysql.user table
@param thd THD @param thd THD
@param host Hostname for the user @param host Hostname for the user
@param user User name @param user User name
@param new_password New password
@param new_password_len The length of the new password
new_password cannot be NULL
@return Error status @return Error status
@retval 0 OK @retval 0 OK
@retval 1 ERROR; In this case the error is sent to the client. @retval 1 skip grant tables error
@retval 2 ANONYMOUS user error
@retval 3 the entry to change is a role, not a user
@retval 4 no UPDATE_ACL error
*/ */
int check_change_password(THD *thd, const char *host, const char *user, int check_alter_user(THD *thd, const char *host, const char *user)
char *new_password, uint new_password_len)
{ {
int error = 1;
if (!initialized) if (!initialized)
{ {
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--skip-grant-tables"); my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--skip-grant-tables");
return(1); goto end;
} }
if (!thd->slave_thread && !thd->security_ctx->priv_user[0]) if (!thd->slave_thread && !thd->security_ctx->priv_user[0])
{ {
my_message(ER_PASSWORD_ANONYMOUS_USER, ER(ER_PASSWORD_ANONYMOUS_USER), my_message(ER_PASSWORD_ANONYMOUS_USER, ER(ER_PASSWORD_ANONYMOUS_USER),
MYF(0)); MYF(0));
return(1); goto end;
} }
if (!host) // Role if (!host) // Role
{ {
my_error(ER_PASSWORD_NO_MATCH, MYF(0)); my_error(ER_PASSWORD_NO_MATCH, MYF(0));
return 1; goto end;
} }
if (!thd->slave_thread && if (!thd->slave_thread &&
(strcmp(thd->security_ctx->priv_user, user) || (strcmp(thd->security_ctx->priv_user, user) ||
...@@ -2560,16 +2578,44 @@ int check_change_password(THD *thd, const char *host, const char *user, ...@@ -2560,16 +2578,44 @@ int check_change_password(THD *thd, const char *host, const char *user,
thd->security_ctx->priv_host))) thd->security_ctx->priv_host)))
{ {
if (check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 0)) if (check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 0))
return(1); goto end;
} }
error = 0;
end:
return error;
}
/**
Check if the user is allowed to change password
@param thd THD
@param host Hostname for the user
@param user User name
@param new_password New password
@param new_password_len The length of the new password
new_password cannot be NULL
@return Error status
@retval 0 OK
@retval 1 ERROR; In this case the error is sent to the client.
*/
int check_change_password(THD *thd, const char *host, const char *user,
char *new_password, uint new_password_len)
{
if (check_alter_user(thd, host, user))
return 1;
size_t len= strlen(new_password); size_t len= strlen(new_password);
if (len && len != SCRAMBLED_PASSWORD_CHAR_LENGTH && if (len && len != SCRAMBLED_PASSWORD_CHAR_LENGTH &&
len != SCRAMBLED_PASSWORD_CHAR_LENGTH_323) len != SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
{ {
my_error(ER_PASSWD_LENGTH, MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH); my_error(ER_PASSWD_LENGTH, MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH);
return -1; return 1;
} }
return(0); return 0;
} }
...@@ -2669,6 +2715,152 @@ bool change_password(THD *thd, const char *host, const char *user, ...@@ -2669,6 +2715,152 @@ bool change_password(THD *thd, const char *host, const char *user,
DBUG_RETURN(result); DBUG_RETURN(result);
} }
int acl_check_set_default_role(THD *thd, const char *host, const char *user)
{
return check_alter_user(thd, host, user);
}
int acl_set_default_role(THD *thd, const char *host, const char *user,
const char *rolename)
{
TABLE_LIST tables;
TABLE *table;
char user_key[MAX_KEY_LENGTH];
int result= 1;
int error;
bool clear_role= FALSE;
Rpl_filter *rpl_filter;
enum_binlog_format save_binlog_format;
DBUG_ENTER("acl_set_default_role");
DBUG_PRINT("enter",("host: '%s' user: '%s' rolename: '%s'",
safe_str(user), safe_str(host), safe_str(rolename)));
if (rolename == current_role.str) {
if (!thd->security_ctx->priv_role[0])
rolename= "NONE";
else
rolename= thd->security_ctx->priv_role;
}
if (check_user_can_set_role(host, user, rolename, NULL))
DBUG_RETURN(result);
if (!strcasecmp(rolename, "NONE"))
clear_role= TRUE;
tables.init_one_table("mysql", 5, "user", 4, "user", TL_WRITE);
#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 &&
(rpl_filter= thd->system_thread_info.rpl_sql_info->rpl_filter)->is_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 (!(thd->spcont || rpl_filter->tables_ok(0, &tables)))
DBUG_RETURN(0);
}
#endif
if (!(table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT)))
DBUG_RETURN(1);
/*
This statement will be replicated as a statement, even when using
row-based replication. The flag will be reset at the end of the
statement.
This has to be handled here as it's called by set_var.cc, which is
not automaticly handled by sql_parse.cc
*/
save_binlog_format= thd->set_current_stmt_binlog_format_stmt();
mysql_mutex_lock(&acl_cache->lock);
ACL_USER *acl_user;
if (!(acl_user= find_user_exact(host, user)))
{
mysql_mutex_unlock(&acl_cache->lock);
my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH), MYF(0));
goto end;
}
if (!clear_role) {
/* set new default_rolename */
acl_user->default_rolename.str= safe_strdup_root(&acl_memroot, rolename);
acl_user->default_rolename.length= strlen(rolename);
}
else
{
/* clear the default_rolename */
acl_user->default_rolename.str = NULL;
acl_user->default_rolename.length = 0;
}
/* update the mysql.user table with the new default role */
table->use_all_columns();
if (table->s->fields < 45)
{
my_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, MYF(0),
table->alias.c_ptr(), DEFAULT_ROLE_COLUMN_IDX + 1, table->s->fields,
static_cast<int>(table->s->mysql_version), MYSQL_VERSION_ID);
mysql_mutex_unlock(&acl_cache->lock);
goto end;
}
table->field[0]->store(host,(uint) strlen(host), system_charset_info);
table->field[1]->store(user,(uint) strlen(user), system_charset_info);
key_copy((uchar *) user_key, table->record[0], table->key_info,
table->key_info->key_length);
if (table->file->ha_index_read_idx_map(table->record[0], 0,
(uchar *) user_key, HA_WHOLE_KEY,
HA_READ_KEY_EXACT))
{
mysql_mutex_unlock(&acl_cache->lock);
my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH), MYF(0));
goto end;
}
store_record(table, record[1]);
table->field[DEFAULT_ROLE_COLUMN_IDX]->store(acl_user->default_rolename.str,
acl_user->default_rolename.length,
system_charset_info);
if ((error=table->file->ha_update_row(table->record[1],table->record[0])) &&
error != HA_ERR_RECORD_IS_THE_SAME)
{
mysql_mutex_unlock(&acl_cache->lock);
table->file->print_error(error,MYF(0)); /* purecov: deadcode */
goto end;
}
acl_cache->clear(1);
mysql_mutex_unlock(&acl_cache->lock);
result= 0;
if (mysql_bin_log.is_open())
{
char buff[512];
int query_length=
sprintf(buff,"SET DEFAULT ROLE '%-.120s' FOR '%-.120s'@'%-.120s'",
safe_str(acl_user->default_rolename.str),
safe_str(acl_user->user.str),
safe_str(acl_user->host.hostname));
thd->clear_error();
result= thd->binlog_query(THD::STMT_QUERY_TYPE, buff, query_length,
FALSE, FALSE, FALSE, 0);
}
end:
close_mysql_tables(thd);
thd->restore_stmt_binlog_format(save_binlog_format);
DBUG_RETURN(result);
}
/* /*
Find user in ACL Find user in ACL
...@@ -12075,6 +12267,22 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len) ...@@ -12075,6 +12267,22 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
*/ */
sctx->db_access=0; sctx->db_access=0;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/*
In case the user has a default role set, attempt to set that role
*/
if (acl_user->default_rolename.length) {
ulonglong access= 0;
int result;
result= acl_check_setrole(thd, acl_user->default_rolename.str, &access);
if (!result)
result= acl_setrole(thd, acl_user->default_rolename.str, access);
if (result)
thd->clear_error(); // even if the default role was not granted, do not
// close the connection
}
#endif
/* Change a database if necessary */ /* Change a database if necessary */
if (mpvio.db.length) if (mpvio.db.length)
{ {
......
...@@ -401,6 +401,9 @@ bool acl_check_proxy_grant_access (THD *thd, const char *host, const char *user, ...@@ -401,6 +401,9 @@ bool acl_check_proxy_grant_access (THD *thd, const char *host, const char *user,
bool with_grant); bool with_grant);
int acl_setrole(THD *thd, char *rolename, ulonglong access); int acl_setrole(THD *thd, char *rolename, ulonglong access);
int acl_check_setrole(THD *thd, char *rolename, ulonglong *access); int acl_check_setrole(THD *thd, char *rolename, ulonglong *access);
int acl_check_set_default_role(THD *thd, const char *host, const char *user);
int acl_set_default_role(THD *thd, const char *host, const char *user,
const char *rolename);
#ifndef DBUG_OFF #ifndef DBUG_OFF
extern ulong role_global_merges, role_db_merges, role_table_merges, extern ulong role_global_merges, role_db_merges, role_table_merges,
......
...@@ -14667,10 +14667,39 @@ option_value_no_option_type: ...@@ -14667,10 +14667,39 @@ option_value_no_option_type:
MYSQL_YYABORT; MYSQL_YYABORT;
lex->var_list.push_back(var); lex->var_list.push_back(var);
} }
| DEFAULT ROLE_SYM grant_role
{
LEX *lex = Lex;
LEX_USER *user;
if (!(user=(LEX_USER *) thd->calloc(sizeof(LEX_USER))))
MYSQL_YYABORT;
user->user= current_user;
set_var_default_role *var= new set_var_default_role(user,
$3->user);
if (var == NULL)
MYSQL_YYABORT;
lex->var_list.push_back(var);
thd->lex->autocommit= TRUE;
if (lex->sphead)
lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
}
| DEFAULT ROLE_SYM grant_role FOR_SYM user
{
LEX *lex = Lex;
set_var_default_role *var= new set_var_default_role($5, $3->user);
if (var == NULL)
MYSQL_YYABORT;
lex->var_list.push_back(var);
thd->lex->autocommit= TRUE;
if (lex->sphead)
lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
}
| ROLE_SYM ident_or_text | ROLE_SYM ident_or_text
{ {
LEX *lex = Lex; LEX *lex = Lex;
set_var_role *var= new set_var_role($2); set_var_role *var= new set_var_role($2);
if (var == NULL)
MYSQL_YYABORT;
lex->var_list.push_back(var); lex->var_list.push_back(var);
} }
| PASSWORD equal text_or_password | PASSWORD equal text_or_password
...@@ -14710,6 +14739,7 @@ option_value_no_option_type: ...@@ -14710,6 +14739,7 @@ option_value_no_option_type:
} }
; ;
internal_variable_name: internal_variable_name:
ident ident
{ {
......
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