summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/alter_user.result93
-rw-r--r--mysql-test/r/create_user.result72
-rw-r--r--mysql-test/r/mysqld--help.result2
-rw-r--r--mysql-test/r/show_create_user.result39
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_server_embedded.result4
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result4
-rw-r--r--mysql-test/t/alter_user.test82
-rw-r--r--mysql-test/t/create_user.test58
-rw-r--r--mysql-test/t/show_create_user.test34
-rw-r--r--sql/mysqld.cc2
-rw-r--r--sql/sp_head.cc2
-rw-r--r--sql/sql_acl.cc315
-rw-r--r--sql/sql_acl.h2
-rw-r--r--sql/sql_cmd.h2
-rw-r--r--sql/sql_parse.cc27
-rw-r--r--sql/sql_yacc.yy81
16 files changed, 701 insertions, 118 deletions
diff --git a/mysql-test/r/alter_user.result b/mysql-test/r/alter_user.result
new file mode 100644
index 00000000000..ac668bba8fa
--- /dev/null
+++ b/mysql-test/r/alter_user.result
@@ -0,0 +1,93 @@
+select * from mysql.user where user = 'root' and host = 'localhost';
+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 max_statement_time
+localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 N N 0.000000
+# Test syntax
+#
+# These 2 selects should have no changes from the first one.
+alter user CURRENT_USER;
+select * from mysql.user where user = 'root' and host = 'localhost';
+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 max_statement_time
+localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 N N 0.000000
+alter user CURRENT_USER();
+select * from mysql.user where user = 'root' and host = 'localhost';
+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 max_statement_time
+localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 N N 0.000000
+create user foo;
+select * from mysql.user where user = 'foo';
+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 max_statement_time
+% foo 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 N 0.000000
+alter user foo;
+select * from mysql.user where user = 'foo';
+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 max_statement_time
+% foo 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 N 0.000000
+# Test super privilege works correctly with a read only database.
+SET @start_read_only = @@global.read_only;
+SET GLOBAL read_only=1;
+grant create user on *.* to foo;
+# Currently no super privileges.
+connect a, localhost, foo;
+select @@global.read_only;
+@@global.read_only
+1
+alter user foo;
+ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
+# Grant super privilege to the user.
+connection default;
+grant super on *.* to foo;
+# We now have super privilege. We should be able to run alter user.
+connect b, localhost, foo;
+alter user foo;
+connection default;
+SET GLOBAL read_only = @start_read_only;
+# Test inexistant user.
+alter user boo;
+ERROR HY000: Operation ALTER USER failed for 'boo'
+#--warning ER_CANNOT_USER
+alter if exists user boo;
+Warnings:
+Error 1133 Can't find any matching row in the user table
+Note 1396 Operation ALTER USER failed for 'boo'
+# Test password related altering.
+alter user foo identified by 'something';
+select * from mysql.user where user = 'foo';
+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 max_statement_time
+% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 0 0 0 0 N N 0.000000
+alter user foo identified by 'something2';
+select * from mysql.user where user = 'foo';
+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 max_statement_time
+% foo *9CD58369E930E28C8996A89DB18B63294E6DC10C N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 0 0 0 0 N N 0.000000
+alter user foo identified by password '*88C89BE093D4ECF72D039F62EBB7477EA1FD4D63';
+select * from mysql.user where user = 'foo';
+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 max_statement_time
+% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 0 0 0 0 N N 0.000000
+alter user foo identified with 'somecoolplugin';
+select * from mysql.user where user = 'foo';
+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 max_statement_time
+% foo N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 0 0 0 0 somecoolplugin N N 0.000000
+alter user foo identified with 'somecoolplugin' using 'somecoolpassphrase';
+select * from mysql.user where user = 'foo';
+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 max_statement_time
+% foo N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 0 0 0 0 somecoolplugin somecoolpassphrase N N 0.000000
+# Test ssl related altering.
+alter user foo identified by 'something' require SSL;
+select * from mysql.user where user = 'foo';
+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 max_statement_time
+% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N ANY 0 0 0 0 N N 0.000000
+alter user foo identified by 'something' require X509;
+select * from mysql.user where user = 'foo';
+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 max_statement_time
+% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N X509 0 0 0 0 N N 0.000000
+alter user foo identified by 'something'
+require cipher 'text' issuer 'foo_issuer' subject 'foo_subject';
+select * from mysql.user where user = 'foo';
+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 max_statement_time
+% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N SPECIFIED text foo_issuer foo_subject 0 0 0 0 N N 0.000000
+# Test resource limits altering.
+alter user foo with MAX_QUERIES_PER_HOUR 10
+MAX_UPDATES_PER_HOUR 20
+MAX_CONNECTIONS_PER_HOUR 30
+MAX_USER_CONNECTIONS 40;
+select * from mysql.user where user = 'foo';
+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 max_statement_time
+% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N SPECIFIED text foo_issuer foo_subject 10 20 30 40 N N 0.000000
+drop user foo;
diff --git a/mysql-test/r/create_user.result b/mysql-test/r/create_user.result
new file mode 100644
index 00000000000..1411f2e8792
--- /dev/null
+++ b/mysql-test/r/create_user.result
@@ -0,0 +1,72 @@
+create user foo;
+select * from mysql.user where user = 'foo';
+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 max_statement_time
+% foo 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 N 0.000000
+drop user foo;
+create user foo identified by 'password';
+select * from mysql.user where user = 'foo';
+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 max_statement_time
+% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 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 N 0.000000
+drop user foo;
+create user foo identified by 'password' require SSL;
+select * from mysql.user where user = 'foo';
+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 max_statement_time
+% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 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 ANY 0 0 0 0 N N 0.000000
+drop user foo;
+create user foo identified by 'password' require X509;
+select * from mysql.user where user = 'foo';
+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 max_statement_time
+% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 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 X509 0 0 0 0 N N 0.000000
+drop user foo;
+create user foo identified by 'password' require CIPHER 'cipher';
+select * from mysql.user where user = 'foo';
+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 max_statement_time
+% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 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 SPECIFIED cipher 0 0 0 0 N N 0.000000
+drop user foo;
+create user foo identified by 'password' require ISSUER 'issuer';
+select * from mysql.user where user = 'foo';
+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 max_statement_time
+% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 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 SPECIFIED issuer 0 0 0 0 N N 0.000000
+drop user foo;
+create user foo identified by 'password' require SUBJECT 'subject';
+select * from mysql.user where user = 'foo';
+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 max_statement_time
+% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 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 SPECIFIED subject 0 0 0 0 N N 0.000000
+drop user foo;
+create user foo identified by 'password' require CIPHER 'cipher'
+ SUBJECT 'subject';
+select * from mysql.user where user = 'foo';
+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 max_statement_time
+% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 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 SPECIFIED cipher subject 0 0 0 0 N N 0.000000
+drop user foo;
+create user foo identified by 'password' require CIPHER 'cipher'
+AND SUBJECT 'subject'
+ AND ISSUER 'issuer';
+select * from mysql.user where user = 'foo';
+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 max_statement_time
+% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 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 SPECIFIED cipher issuer subject 0 0 0 0 N N 0.000000
+drop user foo;
+create user foo, foo2 identified by 'password' require CIPHER 'cipher'
+AND SUBJECT 'subject'
+ AND ISSUER 'issuer';
+select * from mysql.user where user like 'foo';
+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 max_statement_time
+% foo 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 SPECIFIED cipher issuer subject 0 0 0 0 N N 0.000000
+#--warning ER_USER_CREATE_EXISTS
+create user if not exists foo, foo2 identified by 'password2'
+ require CIPHER 'cipher2' AND SUBJECT 'subject2' AND ISSUER 'issuer2';
+Warnings:
+Note 1973 Can't create user 'foo'@'%'; it already exists
+Note 1973 Can't create user 'foo2'@'%'; it already exists
+select * from mysql.user where user like 'foo';
+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 max_statement_time
+% foo 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 SPECIFIED cipher issuer subject 0 0 0 0 N N 0.000000
+drop user foo, foo2;
+create user foo with MAX_QUERIES_PER_HOUR 10
+MAX_UPDATES_PER_HOUR 20
+MAX_CONNECTIONS_PER_HOUR 30
+MAX_USER_CONNECTIONS 40;
+select * from mysql.user where user like 'foo';
+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 max_statement_time
+% foo 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 10 20 30 40 N N 0.000000
+drop user foo;
diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result
index dce1578adee..a008affa9f8 100644
--- a/mysql-test/r/mysqld--help.result
+++ b/mysql-test/r/mysqld--help.result
@@ -1360,7 +1360,7 @@ performance-schema-max-rwlock-instances -1
performance-schema-max-socket-classes 10
performance-schema-max-socket-instances -1
performance-schema-max-stage-classes 150
-performance-schema-max-statement-classes 178
+performance-schema-max-statement-classes 180
performance-schema-max-table-handles -1
performance-schema-max-table-instances -1
performance-schema-max-thread-classes 50
diff --git a/mysql-test/r/show_create_user.result b/mysql-test/r/show_create_user.result
new file mode 100644
index 00000000000..63013eca074
--- /dev/null
+++ b/mysql-test/r/show_create_user.result
@@ -0,0 +1,39 @@
+create user foo;
+show create user foo;
+CREATE USER for foo@%
+CREATE USER 'foo'@'%'
+create user foo@test;
+show create user foo@test;
+CREATE USER for foo@test
+CREATE USER 'foo'@'test'
+create user foo2@test identified by 'password';
+show create user foo2@test;
+CREATE USER for foo2@test
+CREATE USER 'foo2'@'test' IDENTIFIED BY PASSWORD '*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19'
+alter user foo2@test identified with 'someplugin' as 'somepassword';
+show create user foo2@test;
+CREATE USER for foo2@test
+CREATE USER 'foo2'@'test' IDENTIFIED VIA someplugin USING 'somepassword'
+create user foo3@test require SSL;
+show create user foo3@test;
+CREATE USER for foo3@test
+CREATE USER 'foo3'@'test' REQUIRE SSL
+create user foo4@test require cipher 'text' issuer 'foo_issuer' subject 'foo_subject';
+show create user foo4@test;
+CREATE USER for foo4@test
+CREATE USER 'foo4'@'test' REQUIRE ISSUER 'foo_issuer' SUBJECT 'foo_subject' CIPHER 'text'
+create user foo5@test require SSL
+with MAX_QUERIES_PER_HOUR 10
+MAX_UPDATES_PER_HOUR 20
+MAX_CONNECTIONS_PER_HOUR 30
+MAX_USER_CONNECTIONS 40
+MAX_STATEMENT_TIME 0.5;
+show create user foo5@test;
+CREATE USER for foo5@test
+CREATE USER 'foo5'@'test' REQUIRE SSL WITH MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 MAX_CONNECTIONS_PER_HOUR 30 MAX_USER_CONNECTIONS 40 MAX_STATEMENT_TIME 0.500000
+drop user foo5@test;
+drop user foo4@test;
+drop user foo3@test;
+drop user foo2@test;
+drop user foo@test;
+drop user foo;
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
index 865b5a8ca2f..6be27560d89 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
@@ -2825,9 +2825,9 @@ READ_ONLY YES
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES
SESSION_VALUE NULL
-GLOBAL_VALUE 178
+GLOBAL_VALUE 180
GLOBAL_VALUE_ORIGIN COMPILE-TIME
-DEFAULT_VALUE 178
+DEFAULT_VALUE 180
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Maximum number of statement instruments.
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
index 21f1f905de8..4c358fd456a 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
@@ -3021,9 +3021,9 @@ READ_ONLY YES
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES
SESSION_VALUE NULL
-GLOBAL_VALUE 178
+GLOBAL_VALUE 180
GLOBAL_VALUE_ORIGIN COMPILE-TIME
-DEFAULT_VALUE 178
+DEFAULT_VALUE 180
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Maximum number of statement instruments.
diff --git a/mysql-test/t/alter_user.test b/mysql-test/t/alter_user.test
new file mode 100644
index 00000000000..e32d0c29f2e
--- /dev/null
+++ b/mysql-test/t/alter_user.test
@@ -0,0 +1,82 @@
+--source include/not_embedded.inc
+--enable_connect_log
+
+
+select * from mysql.user where user = 'root' and host = 'localhost';
+--echo # Test syntax
+--echo #
+--echo # These 2 selects should have no changes from the first one.
+alter user CURRENT_USER;
+select * from mysql.user where user = 'root' and host = 'localhost';
+alter user CURRENT_USER();
+select * from mysql.user where user = 'root' and host = 'localhost';
+
+create user foo;
+select * from mysql.user where user = 'foo';
+alter user foo;
+select * from mysql.user where user = 'foo';
+
+--echo # Test super privilege works correctly with a read only database.
+SET @start_read_only = @@global.read_only;
+SET GLOBAL read_only=1;
+grant create user on *.* to foo;
+
+--echo # Currently no super privileges.
+connect (a, localhost, foo);
+select @@global.read_only;
+
+--error ER_OPTION_PREVENTS_STATEMENT
+alter user foo;
+
+--echo # Grant super privilege to the user.
+connection default;
+grant super on *.* to foo;
+
+--echo # We now have super privilege. We should be able to run alter user.
+connect (b, localhost, foo);
+alter user foo;
+
+connection default;
+SET GLOBAL read_only = @start_read_only;
+
+--echo # Test inexistant user.
+--error ER_CANNOT_USER
+alter user boo;
+--echo #--warning ER_CANNOT_USER
+alter if exists user boo;
+
+--echo # Test password related altering.
+alter user foo identified by 'something';
+select * from mysql.user where user = 'foo';
+
+alter user foo identified by 'something2';
+select * from mysql.user where user = 'foo';
+
+alter user foo identified by password '*88C89BE093D4ECF72D039F62EBB7477EA1FD4D63';
+select * from mysql.user where user = 'foo';
+
+alter user foo identified with 'somecoolplugin';
+select * from mysql.user where user = 'foo';
+
+alter user foo identified with 'somecoolplugin' using 'somecoolpassphrase';
+select * from mysql.user where user = 'foo';
+
+--echo # Test ssl related altering.
+alter user foo identified by 'something' require SSL;
+select * from mysql.user where user = 'foo';
+
+alter user foo identified by 'something' require X509;
+select * from mysql.user where user = 'foo';
+
+alter user foo identified by 'something'
+require cipher 'text' issuer 'foo_issuer' subject 'foo_subject';
+select * from mysql.user where user = 'foo';
+
+--echo # Test resource limits altering.
+alter user foo with MAX_QUERIES_PER_HOUR 10
+ MAX_UPDATES_PER_HOUR 20
+ MAX_CONNECTIONS_PER_HOUR 30
+ MAX_USER_CONNECTIONS 40;
+select * from mysql.user where user = 'foo';
+drop user foo;
+--disable_connect_log
diff --git a/mysql-test/t/create_user.test b/mysql-test/t/create_user.test
new file mode 100644
index 00000000000..f04cb3e302a
--- /dev/null
+++ b/mysql-test/t/create_user.test
@@ -0,0 +1,58 @@
+--source include/not_embedded.inc
+
+create user foo;
+select * from mysql.user where user = 'foo';
+drop user foo;
+
+create user foo identified by 'password';
+select * from mysql.user where user = 'foo';
+drop user foo;
+
+create user foo identified by 'password' require SSL;
+select * from mysql.user where user = 'foo';
+drop user foo;
+
+create user foo identified by 'password' require X509;
+select * from mysql.user where user = 'foo';
+drop user foo;
+
+create user foo identified by 'password' require CIPHER 'cipher';
+select * from mysql.user where user = 'foo';
+drop user foo;
+
+create user foo identified by 'password' require ISSUER 'issuer';
+select * from mysql.user where user = 'foo';
+drop user foo;
+
+create user foo identified by 'password' require SUBJECT 'subject';
+select * from mysql.user where user = 'foo';
+drop user foo;
+
+create user foo identified by 'password' require CIPHER 'cipher'
+ SUBJECT 'subject';
+select * from mysql.user where user = 'foo';
+drop user foo;
+
+create user foo identified by 'password' require CIPHER 'cipher'
+ AND SUBJECT 'subject'
+ AND ISSUER 'issuer';
+select * from mysql.user where user = 'foo';
+drop user foo;
+
+create user foo, foo2 identified by 'password' require CIPHER 'cipher'
+ AND SUBJECT 'subject'
+ AND ISSUER 'issuer';
+select * from mysql.user where user like 'foo';
+
+--echo #--warning ER_USER_CREATE_EXISTS
+create user if not exists foo, foo2 identified by 'password2'
+ require CIPHER 'cipher2' AND SUBJECT 'subject2' AND ISSUER 'issuer2';
+select * from mysql.user where user like 'foo';
+drop user foo, foo2;
+
+create user foo with MAX_QUERIES_PER_HOUR 10
+ MAX_UPDATES_PER_HOUR 20
+ MAX_CONNECTIONS_PER_HOUR 30
+ MAX_USER_CONNECTIONS 40;
+select * from mysql.user where user like 'foo';
+drop user foo;
diff --git a/mysql-test/t/show_create_user.test b/mysql-test/t/show_create_user.test
new file mode 100644
index 00000000000..a10c8aeeda6
--- /dev/null
+++ b/mysql-test/t/show_create_user.test
@@ -0,0 +1,34 @@
+--source include/not_embedded.inc
+
+create user foo;
+show create user foo;
+
+create user foo@test;
+show create user foo@test;
+
+create user foo2@test identified by 'password';
+show create user foo2@test;
+
+alter user foo2@test identified with 'someplugin' as 'somepassword';
+show create user foo2@test;
+
+create user foo3@test require SSL;
+show create user foo3@test;
+
+create user foo4@test require cipher 'text' issuer 'foo_issuer' subject 'foo_subject';
+show create user foo4@test;
+
+create user foo5@test require SSL
+ with MAX_QUERIES_PER_HOUR 10
+ MAX_UPDATES_PER_HOUR 20
+ MAX_CONNECTIONS_PER_HOUR 30
+ MAX_USER_CONNECTIONS 40
+ MAX_STATEMENT_TIME 0.5;
+show create user foo5@test;
+
+drop user foo5@test;
+drop user foo4@test;
+drop user foo3@test;
+drop user foo2@test;
+drop user foo@test;
+drop user foo;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 8d00b5af948..b28cea5ac46 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -3676,6 +3676,7 @@ SHOW_VAR com_status_vars[]= {
{"alter_server", STMT_STATUS(SQLCOM_ALTER_SERVER)},
{"alter_table", STMT_STATUS(SQLCOM_ALTER_TABLE)},
{"alter_tablespace", STMT_STATUS(SQLCOM_ALTER_TABLESPACE)},
+ {"alter_user", STMT_STATUS(SQLCOM_ALTER_USER)},
{"analyze", STMT_STATUS(SQLCOM_ANALYZE)},
{"assign_to_keycache", STMT_STATUS(SQLCOM_ASSIGN_TO_KEYCACHE)},
{"begin", STMT_STATUS(SQLCOM_BEGIN)},
@@ -3765,6 +3766,7 @@ SHOW_VAR com_status_vars[]= {
{"show_create_proc", STMT_STATUS(SQLCOM_SHOW_CREATE_PROC)},
{"show_create_table", STMT_STATUS(SQLCOM_SHOW_CREATE)},
{"show_create_trigger", STMT_STATUS(SQLCOM_SHOW_CREATE_TRIGGER)},
+ {"show_create_user", STMT_STATUS(SQLCOM_SHOW_CREATE_USER)},
{"show_databases", STMT_STATUS(SQLCOM_SHOW_DATABASES)},
{"show_engine_logs", STMT_STATUS(SQLCOM_SHOW_ENGINE_LOGS)},
{"show_engine_mutex", STMT_STATUS(SQLCOM_SHOW_ENGINE_MUTEX)},
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 0428c0198a1..a27f0ef4250 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -241,6 +241,7 @@ sp_get_flags_for_command(LEX *lex)
case SQLCOM_SHOW_CREATE_PROC:
case SQLCOM_SHOW_CREATE_EVENT:
case SQLCOM_SHOW_CREATE_TRIGGER:
+ case SQLCOM_SHOW_CREATE_USER:
case SQLCOM_SHOW_DATABASES:
case SQLCOM_SHOW_ERRORS:
case SQLCOM_SHOW_EXPLAIN:
@@ -309,6 +310,7 @@ sp_get_flags_for_command(LEX *lex)
case SQLCOM_CREATE_USER:
case SQLCOM_CREATE_ROLE:
case SQLCOM_ALTER_TABLE:
+ case SQLCOM_ALTER_USER:
case SQLCOM_GRANT:
case SQLCOM_GRANT_ROLE:
case SQLCOM_REVOKE:
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index cf0b1d87bd7..2b6ababa8dd 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -7756,6 +7756,94 @@ static void add_user_option(String *grant, double value, const char *name)
}
}
+static void add_user_parameters(String *result, ACL_USER* acl_user,
+ bool with_grant)
+{
+ result->append(STRING_WITH_LEN("@'"));
+ result->append(acl_user->host.hostname, acl_user->hostname_length,
+ system_charset_info);
+ result->append('\'');
+
+ if (acl_user->plugin.str == native_password_plugin_name.str ||
+ acl_user->plugin.str == old_password_plugin_name.str)
+ {
+ if (acl_user->auth_string.length)
+ {
+ DBUG_ASSERT(acl_user->salt_len);
+ result->append(STRING_WITH_LEN(" IDENTIFIED BY PASSWORD '"));
+ result->append(acl_user->auth_string.str, acl_user->auth_string.length);
+ result->append('\'');
+ }
+ }
+ else
+ {
+ result->append(STRING_WITH_LEN(" IDENTIFIED VIA "));
+ result->append(acl_user->plugin.str, acl_user->plugin.length);
+ if (acl_user->auth_string.length)
+ {
+ result->append(STRING_WITH_LEN(" USING '"));
+ result->append(acl_user->auth_string.str, acl_user->auth_string.length);
+ result->append('\'');
+ }
+ }
+ /* "show grants" SSL related stuff */
+ if (acl_user->ssl_type == SSL_TYPE_ANY)
+ result->append(STRING_WITH_LEN(" REQUIRE SSL"));
+ else if (acl_user->ssl_type == SSL_TYPE_X509)
+ result->append(STRING_WITH_LEN(" REQUIRE X509"));
+ else if (acl_user->ssl_type == SSL_TYPE_SPECIFIED)
+ {
+ int ssl_options = 0;
+ result->append(STRING_WITH_LEN(" REQUIRE "));
+ if (acl_user->x509_issuer)
+ {
+ ssl_options++;
+ result->append(STRING_WITH_LEN("ISSUER \'"));
+ result->append(acl_user->x509_issuer,strlen(acl_user->x509_issuer));
+ result->append('\'');
+ }
+ if (acl_user->x509_subject)
+ {
+ if (ssl_options++)
+ result->append(' ');
+ result->append(STRING_WITH_LEN("SUBJECT \'"));
+ result->append(acl_user->x509_subject,strlen(acl_user->x509_subject),
+ system_charset_info);
+ result->append('\'');
+ }
+ if (acl_user->ssl_cipher)
+ {
+ if (ssl_options++)
+ result->append(' ');
+ result->append(STRING_WITH_LEN("CIPHER '"));
+ result->append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher),
+ system_charset_info);
+ result->append('\'');
+ }
+ }
+ if (with_grant ||
+ (acl_user->user_resource.questions ||
+ acl_user->user_resource.updates ||
+ acl_user->user_resource.conn_per_hour ||
+ acl_user->user_resource.user_conn ||
+ acl_user->user_resource.max_statement_time != 0.0))
+ {
+ result->append(STRING_WITH_LEN(" WITH"));
+ if (with_grant)
+ result->append(STRING_WITH_LEN(" GRANT OPTION"));
+ add_user_option(result, acl_user->user_resource.questions,
+ "MAX_QUERIES_PER_HOUR", false);
+ add_user_option(result, acl_user->user_resource.updates,
+ "MAX_UPDATES_PER_HOUR", false);
+ add_user_option(result, acl_user->user_resource.conn_per_hour,
+ "MAX_CONNECTIONS_PER_HOUR", false);
+ add_user_option(result, acl_user->user_resource.user_conn,
+ "MAX_USER_CONNECTIONS", true);
+ add_user_option(result, acl_user->user_resource.max_statement_time,
+ "MAX_STATEMENT_TIME");
+ }
+}
+
static const char *command_array[]=
{
"SELECT", "INSERT", "UPDATE", "DELETE", "CREATE", "DROP", "RELOAD",
@@ -7802,6 +7890,77 @@ static bool print_grants_for_role(THD *thd, ACL_ROLE * role)
}
+bool mysql_show_create_user(THD *thd, LEX_USER *lex_user)
+{
+ const char *username = safe_str(lex_user->user.str);
+ const char *hostname = safe_str(lex_user->host.str);
+ char buff[1024]; //Show create user should not take more than 1024 bytes.
+ Protocol *protocol= thd->protocol;
+ bool error= false;
+ ACL_USER *acl_user;
+ DBUG_ENTER("mysql_show_create_user");
+
+ // Check if the command specifies a username or not.
+ if (lex_user->user.str == current_user.str)
+ {
+ username= thd->security_ctx->priv_user;
+ hostname= thd->security_ctx->priv_host;
+ }
+
+ List<Item> field_list;
+ strxmov(buff, "CREATE USER for ", username, "@", hostname, NullS);
+ Item_string *field = new (thd->mem_root) Item_string_ascii(thd, "", 0);
+ if (!field)
+ {
+ my_error(ER_OUTOFMEMORY, MYF(0));
+ DBUG_RETURN(true);
+ }
+
+ field->name= buff;
+ field->max_length= sizeof(buff);
+ field_list.push_back(field, thd->mem_root);
+ if (protocol->send_result_set_metadata(&field_list,
+ Protocol::SEND_NUM_ROWS |
+ Protocol::SEND_EOF))
+ DBUG_RETURN(true);
+
+ String result(buff, sizeof(buff), system_charset_info);
+ result.length(0);
+ mysql_rwlock_rdlock(&LOCK_grant);
+ mysql_mutex_lock(&acl_cache->lock);
+
+ acl_user= find_user_exact(hostname, username);
+
+ // User not found in the internal data structures.
+ if (!acl_user)
+ {
+ my_error(ER_PASSWORD_NO_MATCH, MYF(0));
+ error= true;
+ goto end;
+ }
+
+ result.append("CREATE USER '");
+ result.append(username);
+ result.append('\'');
+
+ add_user_parameters(&result, acl_user, false);
+
+ protocol->prepare_for_resend();
+ protocol->store(result.ptr(), result.length(), result.charset());
+ if (protocol->write())
+ {
+ error= true;
+ }
+ my_eof(thd);
+
+end:
+ mysql_rwlock_unlock(&LOCK_grant);
+ mysql_mutex_unlock(&acl_cache->lock);
+
+ DBUG_RETURN(error);
+}
+
+
static int show_grants_callback(ACL_USER_BASE *role, void *data)
{
THD *thd= (THD *)data;
@@ -7811,7 +7970,6 @@ static int show_grants_callback(ACL_USER_BASE *role, void *data)
return 0;
}
-
void mysql_show_grants_get_fields(THD *thd, List<Item> *fields,
const char *name)
{
@@ -8086,93 +8244,7 @@ static bool show_global_privileges(THD *thd, ACL_USER_BASE *acl_entry,
global.append('\'');
if (!handle_as_role)
- {
- ACL_USER *acl_user= (ACL_USER *)acl_entry;
-
- global.append (STRING_WITH_LEN("@'"));
- global.append(acl_user->host.hostname, acl_user->hostname_length,
- system_charset_info);
- global.append ('\'');
-
- if (acl_user->plugin.str == native_password_plugin_name.str ||
- acl_user->plugin.str == old_password_plugin_name.str)
- {
- if (acl_user->auth_string.length)
- {
- DBUG_ASSERT(acl_user->salt_len);
- global.append(STRING_WITH_LEN(" IDENTIFIED BY PASSWORD '"));
- global.append(acl_user->auth_string.str, acl_user->auth_string.length);
- global.append('\'');
- }
- }
- else
- {
- global.append(STRING_WITH_LEN(" IDENTIFIED VIA "));
- global.append(acl_user->plugin.str, acl_user->plugin.length);
- if (acl_user->auth_string.length)
- {
- global.append(STRING_WITH_LEN(" USING '"));
- global.append(acl_user->auth_string.str, acl_user->auth_string.length);
- global.append('\'');
- }
- }
- /* "show grants" SSL related stuff */
- if (acl_user->ssl_type == SSL_TYPE_ANY)
- global.append(STRING_WITH_LEN(" REQUIRE SSL"));
- else if (acl_user->ssl_type == SSL_TYPE_X509)
- global.append(STRING_WITH_LEN(" REQUIRE X509"));
- else if (acl_user->ssl_type == SSL_TYPE_SPECIFIED)
- {
- int ssl_options = 0;
- global.append(STRING_WITH_LEN(" REQUIRE "));
- if (acl_user->x509_issuer)
- {
- ssl_options++;
- global.append(STRING_WITH_LEN("ISSUER \'"));
- global.append(acl_user->x509_issuer,strlen(acl_user->x509_issuer));
- global.append('\'');
- }
- if (acl_user->x509_subject)
- {
- if (ssl_options++)
- global.append(' ');
- global.append(STRING_WITH_LEN("SUBJECT \'"));
- global.append(acl_user->x509_subject,strlen(acl_user->x509_subject),
- system_charset_info);
- global.append('\'');
- }
- if (acl_user->ssl_cipher)
- {
- if (ssl_options++)
- global.append(' ');
- global.append(STRING_WITH_LEN("CIPHER '"));
- global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher),
- system_charset_info);
- global.append('\'');
- }
- }
- if ((want_access & GRANT_ACL) ||
- (acl_user->user_resource.questions ||
- acl_user->user_resource.updates ||
- acl_user->user_resource.conn_per_hour ||
- acl_user->user_resource.user_conn ||
- acl_user->user_resource.max_statement_time != 0.0))
- {
- global.append(STRING_WITH_LEN(" WITH"));
- if (want_access & GRANT_ACL)
- global.append(STRING_WITH_LEN(" GRANT OPTION"));
- add_user_option(&global, acl_user->user_resource.questions,
- "MAX_QUERIES_PER_HOUR", false);
- add_user_option(&global, acl_user->user_resource.updates,
- "MAX_UPDATES_PER_HOUR", false);
- add_user_option(&global, acl_user->user_resource.conn_per_hour,
- "MAX_CONNECTIONS_PER_HOUR", false);
- add_user_option(&global, acl_user->user_resource.user_conn,
- "MAX_USER_CONNECTIONS", true);
- add_user_option(&global, acl_user->user_resource.max_statement_time,
- "MAX_STATEMENT_TIME");
- }
- }
+ add_user_parameters(&global, (ACL_USER *)acl_entry, (want_access & GRANT_ACL));
protocol->prepare_for_resend();
protocol->store(global.ptr(),global.length(),global.charset());
@@ -9840,6 +9912,73 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
DBUG_RETURN(result);
}
+/*
+ Alter a user's connection and resource settings.
+
+ SYNOPSIS
+ mysql_alter_user()
+ thd The current thread.
+ list The users to alter.
+
+ RETURN
+ > 0 Error. Error message already sent.
+ 0 OK.
+*/
+int mysql_alter_user(THD* thd, List<LEX_USER> &users_list)
+{
+ DBUG_ENTER("mysql_alter_user");
+ int result= 0;
+ TABLE_LIST tables[TABLES_MAX];
+ String wrong_users;
+ // The only table we're altering is the user table.
+ if ((result= open_grant_tables(thd, tables, TL_WRITE, Table_user)))
+ DBUG_RETURN(result);
+
+ // Lock ACL data structures until we finish altering all users.
+ mysql_rwlock_wrlock(&LOCK_grant);
+ mysql_mutex_lock(&acl_cache->lock);
+
+ LEX_USER *tmp_lex_user;
+ List_iterator<LEX_USER> users_list_iterator(users_list);
+ while ((tmp_lex_user= users_list_iterator++))
+ {
+ LEX_USER* lex_user= get_current_user(thd, tmp_lex_user, false);
+ if (!lex_user ||
+ fix_lex_user(thd, lex_user) ||
+ replace_user_table(thd, tables[USER_TABLE].table, *lex_user,0,
+ false, false, true))
+ {
+ thd->clear_error();
+ append_user(thd, &wrong_users, tmp_lex_user);
+ result= TRUE;
+ continue;
+ }
+ }
+
+ // Unlock ACL data structures.
+ mysql_mutex_unlock(&acl_cache->lock);
+ mysql_rwlock_unlock(&LOCK_grant);
+
+ if (result)
+ {
+ // 'if exists' flag leads to warnings instead of errors.
+ if (thd->lex->create_info.if_exists())
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
+ ER_CANNOT_USER,
+ ER_THD(thd, ER_CANNOT_USER),
+ "ALTER USER", wrong_users.c_ptr_safe());
+ result= FALSE;
+ }
+ else
+ {
+ my_error(ER_CANNOT_USER, MYF(0),
+ "ALTER USER",
+ wrong_users.c_ptr_safe());
+ }
+ }
+ DBUG_RETURN(result);
+}
/*
Revoke all privileges from a list of users.
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index 3bd896cab79..b480d488bc3 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -246,6 +246,7 @@ bool get_show_user(THD *thd, LEX_USER *lex_user, const char **username,
void mysql_show_grants_get_fields(THD *thd, List<Item> *fields,
const char *name);
bool mysql_show_grants(THD *thd, LEX_USER *user);
+bool mysql_show_create_user(THD *thd, LEX_USER *user);
int fill_schema_enabled_roles(THD *thd, TABLE_LIST *tables, COND *cond);
int fill_schema_applicable_roles(THD *thd, TABLE_LIST *tables, COND *cond);
void get_privilege_desc(char *to, uint max_length, ulong access);
@@ -253,6 +254,7 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc);
bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role);
bool mysql_drop_user(THD *thd, List <LEX_USER> &list, bool handle_as_role);
bool mysql_rename_user(THD *thd, List <LEX_USER> &list);
+int mysql_alter_user(THD *thd, List <LEX_USER> &list);
bool mysql_revoke_all(THD *thd, List <LEX_USER> &list);
void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant,
const char *db, const char *table);
diff --git a/sql/sql_cmd.h b/sql/sql_cmd.h
index c237bb9270a..2350b4be56c 100644
--- a/sql/sql_cmd.h
+++ b/sql/sql_cmd.h
@@ -93,6 +93,8 @@ enum enum_sql_command {
SQLCOM_CREATE_ROLE, SQLCOM_DROP_ROLE, SQLCOM_GRANT_ROLE, SQLCOM_REVOKE_ROLE,
SQLCOM_COMPOUND,
SQLCOM_SHOW_GENERIC,
+ SQLCOM_ALTER_USER,
+ SQLCOM_SHOW_CREATE_USER,
/*
When a command is added here, be sure it's also added in mysqld.cc
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 14ac657862f..a5837585b7d 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -422,6 +422,7 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_SHOW_EXPLAIN]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_PROCESSLIST]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_GRANTS]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_CREATE_USER]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE_DB]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_MASTER_STAT]= CF_STATUS_COMMAND;
@@ -443,6 +444,7 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_CREATE_USER]= CF_CHANGES_DATA;
sql_command_flags[SQLCOM_RENAME_USER]= CF_CHANGES_DATA;
sql_command_flags[SQLCOM_DROP_USER]= CF_CHANGES_DATA;
+ sql_command_flags[SQLCOM_ALTER_USER]= CF_CHANGES_DATA;
sql_command_flags[SQLCOM_CREATE_ROLE]= CF_CHANGES_DATA;
sql_command_flags[SQLCOM_GRANT]= CF_CHANGES_DATA;
sql_command_flags[SQLCOM_GRANT_ROLE]= CF_CHANGES_DATA;
@@ -506,6 +508,7 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_CHECKSUM]= CF_REPORT_PROGRESS;
sql_command_flags[SQLCOM_CREATE_USER]|= CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_ALTER_USER]|= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_DROP_USER]|= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_RENAME_USER]|= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_CREATE_ROLE]|= CF_AUTO_COMMIT_TRANS;
@@ -601,6 +604,7 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_ALTER_EVENT]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_DROP_EVENT]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_CREATE_USER]|= CF_DISALLOW_IN_RO_TRANS;
+ sql_command_flags[SQLCOM_ALTER_USER]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_RENAME_USER]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_DROP_USER]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_CREATE_SERVER]|= CF_DISALLOW_IN_RO_TRANS;
@@ -4403,6 +4407,7 @@ mysql_execute_command(THD *thd)
my_ok(thd);
break;
}
+ case SQLCOM_ALTER_USER:
case SQLCOM_RENAME_USER:
{
if (check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 1) &&
@@ -4410,7 +4415,11 @@ mysql_execute_command(THD *thd)
break;
/* Conditionally writes to binlog */
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
- if (!(res= mysql_rename_user(thd, lex->users_list)))
+ if (lex->sql_command == SQLCOM_ALTER_USER)
+ res= mysql_alter_user(thd, lex->users_list);
+ else
+ res= mysql_rename_user(thd, lex->users_list);
+ if (!res)
my_ok(thd);
break;
}
@@ -4707,6 +4716,7 @@ mysql_execute_command(THD *thd)
break;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ case SQLCOM_SHOW_CREATE_USER:
case SQLCOM_SHOW_GRANTS:
{
LEX_USER *grant_user= lex->grant_user;
@@ -4714,7 +4724,20 @@ mysql_execute_command(THD *thd)
goto error;
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW);
- res = mysql_show_grants(thd, grant_user);
+ if (grant_user->user.str && !strcmp(sctx->priv_user, grant_user->user.str) &&
+ grant_user->host.str && !strcmp(sctx->priv_host, grant_user->host.str))
+ grant_user->user= current_user;
+
+ if (grant_user->user.str == current_user.str ||
+ grant_user->user.str == current_role.str ||
+ grant_user->user.str == current_user_and_current_role.str ||
+ !check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 0))
+ {
+ if (lex->sql_command == SQLCOM_SHOW_GRANTS)
+ res = mysql_show_grants(thd, grant_user);
+ else
+ res = mysql_show_create_user(thd, grant_user);
+ }
break;
}
#endif
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 2a46bb2a027..6799781f5e0 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -2531,7 +2531,8 @@ create:
Lex->create_view_suid= TRUE;
}
view_or_trigger_or_sp_or_event { }
- | create_or_replace USER_SYM opt_if_not_exists clear_privileges grant_list
+ | create_or_replace USER opt_if_not_exists clear_privileges grant_list
+ opt_require_clause opt_resource_options
{
if (Lex->set_command_with_check(SQLCOM_CREATE_USER, $1 | $3))
MYSQL_YYABORT;
@@ -7106,6 +7107,13 @@ alter:
lex->sql_command= SQLCOM_ALTER_SERVER;
lex->server_options.reset($3);
} OPTIONS_SYM '(' server_options_list ')' { }
+ /* ALTER USER foo is allowed for MySQL compatibility. */
+ | ALTER opt_if_exists USER clear_privileges grant_list
+ opt_require_clause opt_resource_options
+ {
+ Lex->create_info.set($2);
+ Lex->sql_command= SQLCOM_ALTER_USER;
+ }
;
ev_alter_on_schedule_completion:
@@ -12486,6 +12494,18 @@ show_param:
lex->sql_command= SQLCOM_SHOW_CREATE_TRIGGER;
lex->spname= $3;
}
+ | CREATE USER
+ {
+ Lex->sql_command= SQLCOM_SHOW_CREATE_USER;
+ if (!(Lex->grant_user= (LEX_USER*)thd->alloc(sizeof(LEX_USER))))
+ MYSQL_YYABORT;
+ Lex->grant_user->user= current_user;
+ }
+ | CREATE USER user
+ {
+ Lex->sql_command= SQLCOM_SHOW_CREATE_USER;
+ Lex->grant_user= $3;
+ }
| PROCEDURE_SYM STATUS_SYM wild_and_where
{
LEX *lex= Lex;
@@ -15036,14 +15056,14 @@ grant:
grant_command:
grant_privileges ON opt_table grant_ident TO_SYM grant_list
- require_clause grant_options
+ opt_require_clause opt_grant_options
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_GRANT;
lex->type= 0;
}
| grant_privileges ON FUNCTION_SYM grant_ident TO_SYM grant_list
- require_clause grant_options
+ opt_require_clause opt_grant_options
{
LEX *lex= Lex;
if (lex->columns.elements)
@@ -15055,7 +15075,7 @@ grant_command:
lex->type= TYPE_ENUM_FUNCTION;
}
| grant_privileges ON PROCEDURE_SYM grant_ident TO_SYM grant_list
- require_clause grant_options
+ opt_require_clause opt_grant_options
{
LEX *lex= Lex;
if (lex->columns.elements)
@@ -15392,7 +15412,7 @@ column_list_id:
}
;
-require_clause:
+opt_require_clause:
/* empty */
| REQUIRE_SYM require_list
{
@@ -15412,24 +15432,8 @@ require_clause:
}
;
-grant_options:
- /* empty */ {}
- | WITH grant_option_list
- ;
-
-opt_grant_option:
- /* empty */ {}
- | WITH GRANT OPTION { Lex->grant |= GRANT_ACL;}
- ;
-
-grant_option_list:
- grant_option_list grant_option {}
- | grant_option {}
- ;
-
-grant_option:
- GRANT OPTION { Lex->grant |= GRANT_ACL;}
- | MAX_QUERIES_PER_HOUR ulong_num
+resource_option:
+ MAX_QUERIES_PER_HOUR ulong_num
{
LEX *lex=Lex;
lex->mqh.questions=$2;
@@ -15461,6 +15465,37 @@ grant_option:
}
;
+resource_option_list:
+ resource_option_list resource_option {}
+ | resource_option {}
+ ;
+
+opt_resource_options:
+ /* empty */ {}
+ | WITH resource_option_list
+ ;
+
+
+opt_grant_options:
+ /* empty */ {}
+ | WITH grant_option_list {}
+ ;
+
+opt_grant_option:
+ /* empty */ {}
+ | WITH GRANT OPTION { Lex->grant |= GRANT_ACL;}
+ ;
+
+grant_option_list:
+ grant_option_list grant_option {}
+ | grant_option {}
+ ;
+
+grant_option:
+ GRANT OPTION { Lex->grant |= GRANT_ACL;}
+ | resource_option {}
+ ;
+
begin:
BEGIN_SYM
{