diff options
author | Vicențiu Ciorbaru <vicentiu@mariadb.org> | 2017-02-13 14:40:51 +0200 |
---|---|---|
committer | Vicențiu Ciorbaru <vicentiu@mariadb.org> | 2017-02-14 07:46:58 +0200 |
commit | d731ce21a7bc25a49958789d24b3f0eec5845aea (patch) | |
tree | fbd2599fccabb797f0b3ada9c96409da708057f4 | |
parent | 5ab93737be716721e7b5a9a87206dbdc52b7a649 (diff) | |
download | mariadb-git-d731ce21a7bc25a49958789d24b3f0eec5845aea.tar.gz |
MDEV-11170: MariaDB 10.2 cannot start on MySQL 5.7 datadir
PART 2 of the fix adds the logic of not using password column, unless it
exists. If password column is missing we attempt to use plugin &&
authentication_string columns.
-rw-r--r-- | mysql-test/r/no_password_column-mdev-11170.result | 168 | ||||
-rw-r--r-- | mysql-test/t/no_password_column-mdev-11170.test | 95 | ||||
-rw-r--r-- | sql/sql_acl.cc | 218 |
3 files changed, 412 insertions, 69 deletions
diff --git a/mysql-test/r/no_password_column-mdev-11170.result b/mysql-test/r/no_password_column-mdev-11170.result new file mode 100644 index 00000000000..81eecc95558 --- /dev/null +++ b/mysql-test/r/no_password_column-mdev-11170.result @@ -0,0 +1,168 @@ +# +# MDEV-11170: MariaDB 10.2 cannot start on MySQL 5.7 datadir: +# Fatal error: mysql.user table is damaged or in +# unsupported 3.20 format +# +create table backup_user like mysql.user; +insert into backup_user select * from mysql.user; +# +# Original mysql.user table +# +describe mysql.user; +Field Type Null Key Default Extra +Host char(60) NO PRI +User char(80) NO PRI +Password char(41) NO +Select_priv enum('N','Y') NO N +Insert_priv enum('N','Y') NO N +Update_priv enum('N','Y') NO N +Delete_priv enum('N','Y') NO N +Create_priv enum('N','Y') NO N +Drop_priv enum('N','Y') NO N +Reload_priv enum('N','Y') NO N +Shutdown_priv enum('N','Y') NO N +Process_priv enum('N','Y') NO N +File_priv enum('N','Y') NO N +Grant_priv enum('N','Y') NO N +References_priv enum('N','Y') NO N +Index_priv enum('N','Y') NO N +Alter_priv enum('N','Y') NO N +Show_db_priv enum('N','Y') NO N +Super_priv enum('N','Y') NO N +Create_tmp_table_priv enum('N','Y') NO N +Lock_tables_priv enum('N','Y') NO N +Execute_priv enum('N','Y') NO N +Repl_slave_priv enum('N','Y') NO N +Repl_client_priv enum('N','Y') NO N +Create_view_priv enum('N','Y') NO N +Show_view_priv enum('N','Y') NO N +Create_routine_priv enum('N','Y') NO N +Alter_routine_priv enum('N','Y') NO N +Create_user_priv enum('N','Y') NO N +Event_priv enum('N','Y') NO N +Trigger_priv enum('N','Y') NO N +Create_tablespace_priv enum('N','Y') NO N +ssl_type enum('','ANY','X509','SPECIFIED') NO +ssl_cipher blob NO NULL +x509_issuer blob NO NULL +x509_subject blob NO NULL +max_questions int(11) unsigned NO 0 +max_updates int(11) unsigned NO 0 +max_connections int(11) unsigned NO 0 +max_user_connections int(11) NO 0 +plugin char(64) NO +authentication_string text NO NULL +password_expired enum('N','Y') NO N +is_role enum('N','Y') NO N +default_role char(80) NO +max_statement_time decimal(12,6) NO 0.000000 +# +# Drop the password column. +# +alter table mysql.user drop column password; +flush privileges; +# +# Create users without the password column present. +# +create user foo; +create user goo identified by "foo"; +select OLD_PASSWORD("ioo"); +OLD_PASSWORD("ioo") +7a8f886d28473e85 +create user ioo identified with "mysql_old_password" as "7a8f886d28473e85"; +# +# Check if users have grants loaded correctly. +# +show grants for foo; +Grants for foo@% +GRANT USAGE ON *.* TO 'foo'@'%' +show grants for goo; +Grants for goo@% +GRANT USAGE ON *.* TO 'goo'@'%' IDENTIFIED BY PASSWORD '*F3A2A51A9B0F2BE2468926B4132313728C250DBF' +show grants for ioo; +Grants for ioo@% +GRANT USAGE ON *.* TO 'ioo'@'%' IDENTIFIED BY PASSWORD '7a8f886d28473e85' +select user, host, select_priv, plugin, authentication_string from mysql.user +where user like "%oo" +order by user; +user host select_priv plugin authentication_string +foo % N +goo % N mysql_native_password *F3A2A51A9B0F2BE2468926B4132313728C250DBF +ioo % N mysql_old_password 7a8f886d28473e85 +# +# Test setting password. +# +SET PASSWORD FOR foo=PASSWORD("bar"); +show grants for foo; +Grants for foo@% +GRANT USAGE ON *.* TO 'foo'@'%' IDENTIFIED BY PASSWORD '*E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB' +show grants for goo; +Grants for goo@% +GRANT USAGE ON *.* TO 'goo'@'%' IDENTIFIED BY PASSWORD '*F3A2A51A9B0F2BE2468926B4132313728C250DBF' +show grants for ioo; +Grants for ioo@% +GRANT USAGE ON *.* TO 'ioo'@'%' IDENTIFIED BY PASSWORD '7a8f886d28473e85' +select user, host, select_priv, plugin, authentication_string from mysql.user +where user like "%oo" +order by user; +user host select_priv plugin authentication_string +foo % N mysql_native_password *E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB +goo % N mysql_native_password *F3A2A51A9B0F2BE2468926B4132313728C250DBF +ioo % N mysql_old_password 7a8f886d28473e85 +# +# Test flush privileges without password column. +# +flush privileges; +show grants for foo; +Grants for foo@% +GRANT USAGE ON *.* TO 'foo'@'%' IDENTIFIED BY PASSWORD '*E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB' +show grants for goo; +Grants for goo@% +GRANT USAGE ON *.* TO 'goo'@'%' IDENTIFIED BY PASSWORD '*F3A2A51A9B0F2BE2468926B4132313728C250DBF' +show grants for ioo; +Grants for ioo@% +GRANT USAGE ON *.* TO 'ioo'@'%' IDENTIFIED BY PASSWORD '7a8f886d28473e85' +# +# Test granting of privileges. +# +grant select on *.* to foo; +grant select on *.* to goo; +grant select on *.* to ioo; +show grants for foo; +Grants for foo@% +GRANT SELECT ON *.* TO 'foo'@'%' IDENTIFIED BY PASSWORD '*E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB' +show grants for goo; +Grants for goo@% +GRANT SELECT ON *.* TO 'goo'@'%' IDENTIFIED BY PASSWORD '*F3A2A51A9B0F2BE2468926B4132313728C250DBF' +show grants for ioo; +Grants for ioo@% +GRANT SELECT ON *.* TO 'ioo'@'%' IDENTIFIED BY PASSWORD '7a8f886d28473e85' +# +# Check to see if grants are stable on flush. +# +flush privileges; +show grants for foo; +Grants for foo@% +GRANT SELECT ON *.* TO 'foo'@'%' IDENTIFIED BY PASSWORD '*E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB' +show grants for goo; +Grants for goo@% +GRANT SELECT ON *.* TO 'goo'@'%' IDENTIFIED BY PASSWORD '*F3A2A51A9B0F2BE2468926B4132313728C250DBF' +show grants for ioo; +Grants for ioo@% +GRANT SELECT ON *.* TO 'ioo'@'%' IDENTIFIED BY PASSWORD '7a8f886d28473e85' +# +# Check internal table representation. +# +select user, host, select_priv, plugin, authentication_string from mysql.user +where user like "%oo" +order by user; +user host select_priv plugin authentication_string +foo % Y mysql_native_password *E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB +goo % Y mysql_native_password *F3A2A51A9B0F2BE2468926B4132313728C250DBF +ioo % Y mysql_old_password 7a8f886d28473e85 +# +# Reset to final original state. +# +drop table mysql.user; +rename table backup_user to mysql.user; +flush privileges; diff --git a/mysql-test/t/no_password_column-mdev-11170.test b/mysql-test/t/no_password_column-mdev-11170.test new file mode 100644 index 00000000000..2cc4ba82ee8 --- /dev/null +++ b/mysql-test/t/no_password_column-mdev-11170.test @@ -0,0 +1,95 @@ +--source include/not_embedded.inc +--echo # +--echo # MDEV-11170: MariaDB 10.2 cannot start on MySQL 5.7 datadir: +--echo # Fatal error: mysql.user table is damaged or in +--echo # unsupported 3.20 format +--echo # + + +create table backup_user like mysql.user; +insert into backup_user select * from mysql.user; + +--echo # +--echo # Original mysql.user table +--echo # +describe mysql.user; + +--echo # +--echo # Drop the password column. +--echo # +alter table mysql.user drop column password; +flush privileges; + +--echo # +--echo # Create users without the password column present. +--echo # +create user foo; +create user goo identified by "foo"; +select OLD_PASSWORD("ioo"); +create user ioo identified with "mysql_old_password" as "7a8f886d28473e85"; + +--echo # +--echo # Check if users have grants loaded correctly. +--echo # +show grants for foo; +show grants for goo; +show grants for ioo; + +select user, host, select_priv, plugin, authentication_string from mysql.user +where user like "%oo" +order by user; + +--echo # +--echo # Test setting password. +--echo # +SET PASSWORD FOR foo=PASSWORD("bar"); + +show grants for foo; +show grants for goo; +show grants for ioo; + +select user, host, select_priv, plugin, authentication_string from mysql.user +where user like "%oo" +order by user; + +--echo # +--echo # Test flush privileges without password column. +--echo # +flush privileges; +show grants for foo; +show grants for goo; +show grants for ioo; + +--echo # +--echo # Test granting of privileges. +--echo # +grant select on *.* to foo; +grant select on *.* to goo; +grant select on *.* to ioo; +show grants for foo; +show grants for goo; +show grants for ioo; + +--echo # +--echo # Check to see if grants are stable on flush. +--echo # +flush privileges; +show grants for foo; +show grants for goo; +show grants for ioo; + +--echo # +--echo # Check internal table representation. +--echo # +select user, host, select_priv, plugin, authentication_string from mysql.user +where user like "%oo" +order by user; + + +--echo # +--echo # Reset to final original state. +--echo # +drop table mysql.user; +rename table backup_user to mysql.user; + +flush privileges; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index dd0c302ae04..ab0ed527bc3 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -932,41 +932,44 @@ class Grant_table_base class User_table: public Grant_table_base { public: + /* Field getters return NULL if the column is not present in the table. + This is consistent only if the table is in a supported version. We do + not guard against corrupt tables. (yet) */ Field* host() const - { return tl.table->field[0]; } + { return get_field(0); } Field* user() const - { return tl.table->field[1]; } + { return get_field(1); } Field* password() const - { return tl.table->field[2]; } + { return have_password() ? NULL : tl.table->field[2]; } /* Columns after privilege columns. */ Field* ssl_type() const - { return tl.table->field[start_privilege_column + num_privileges()]; } + { return get_field(start_privilege_column + num_privileges()); } Field* ssl_cipher() const - { return tl.table->field[start_privilege_column + num_privileges() + 1]; } + { return get_field(start_privilege_column + num_privileges() + 1); } Field* x509_issuer() const - { return tl.table->field[start_privilege_column + num_privileges() + 2]; } + { return get_field(start_privilege_column + num_privileges() + 2); } Field* x509_subject() const - { return tl.table->field[start_privilege_column + num_privileges() + 3]; } + { return get_field(start_privilege_column + num_privileges() + 3); } Field* max_questions() const - { return tl.table->field[start_privilege_column + num_privileges() + 4]; } + { return get_field(start_privilege_column + num_privileges() + 4); } Field* max_updates() const - { return tl.table->field[start_privilege_column + num_privileges() + 5]; } + { return get_field(start_privilege_column + num_privileges() + 5); } Field* max_connections() const - { return tl.table->field[start_privilege_column + num_privileges() + 6]; } + { return get_field(start_privilege_column + num_privileges() + 6); } Field* max_user_connections() const - { return tl.table->field[start_privilege_column + num_privileges() + 7]; } + { return get_field(start_privilege_column + num_privileges() + 7); } Field* plugin() const - { return tl.table->field[start_privilege_column + num_privileges() + 8]; } + { return get_field(start_privilege_column + num_privileges() + 8); } Field* authentication_string() const - { return tl.table->field[start_privilege_column + num_privileges() + 9]; } + { return get_field(start_privilege_column + num_privileges() + 9); } Field* password_expired() const - { return tl.table->field[start_privilege_column + num_privileges() + 10]; } + { return get_field(start_privilege_column + num_privileges() + 10); } Field* is_role() const - { return tl.table->field[start_privilege_column + num_privileges() + 11]; } + { return get_field(start_privilege_column + num_privileges() + 11); } Field* default_role() const - { return tl.table->field[start_privilege_column + num_privileges() + 12]; } + { return get_field(start_privilege_column + num_privileges() + 12); } Field* max_statement_time() const - { return tl.table->field[start_privilege_column + num_privileges() + 13]; } + { return get_field(start_privilege_column + num_privileges() + 13); } /* Check if a user entry in the user table is marked as being a role entry @@ -987,7 +990,7 @@ class User_table: public Grant_table_base bool check_is_role() const { /* Table version does not support roles */ - if (num_fields() < 44) + if (!is_role()) return false; return get_YN_as_bool(is_role()); @@ -1008,6 +1011,30 @@ class User_table: public Grant_table_base NULL, lock_type); Grant_table_base::init(lock_type, false); } + + /* The user table is a bit different compared to the other Grant tables. + Usually, we only add columns to the grant tables when adding functionality. + This makes it easy to test which version of the table we are using, by + just looking at the number of fields present in the table. + + In MySQL 5.7.6 the Password column was removed. We need to guard for that. + The field-fetching methods for the User table return NULL if the field + doesn't exist. This simplifies checking of table "version", as we don't + have to make use of num_fields() any more. + */ + inline Field* get_field(uint field_num) const + { + if (field_num >= num_fields()) + return NULL; + + return tl.table->field[field_num]; + } + + /* Normally password column is the third column in the table. If privileges + start on the third column instead, we are missing the password column. + This means we are using a MySQL 5.7.6+ data directory. */ + bool have_password() const { return start_privilege_column == 2; } + }; class Db_table: public Grant_table_base @@ -1849,47 +1876,50 @@ static bool acl_load(THD *thd, const Grant_tables& tables) username_char_length= MY_MIN(user_table.user()->char_length(), USERNAME_CHAR_LENGTH); - password_length= user_table.password()->field_length / - user_table.password()->charset()->mbmaxlen; - if (password_length < SCRAMBLED_PASSWORD_CHAR_LENGTH_323) + if (user_table.password()) // Password column might be missing. (MySQL 5.7.6+) { - sql_print_error("Fatal error: mysql.user table is damaged or in " - "unsupported 3.20 format."); - DBUG_RETURN(TRUE); - } + password_length= user_table.password()->field_length / + user_table.password()->charset()->mbmaxlen; + if (password_length < SCRAMBLED_PASSWORD_CHAR_LENGTH_323) + { + sql_print_error("Fatal error: mysql.user table is damaged or in " + "unsupported 3.20 format."); + DBUG_RETURN(TRUE); + } - DBUG_PRINT("info",("user table fields: %d, password length: %d", - user_table.num_fields(), password_length)); + DBUG_PRINT("info",("user table fields: %d, password length: %d", + user_table.num_fields(), password_length)); - mysql_mutex_lock(&LOCK_global_system_variables); - if (password_length < SCRAMBLED_PASSWORD_CHAR_LENGTH) - { - if (opt_secure_auth) + mysql_mutex_lock(&LOCK_global_system_variables); + if (password_length < SCRAMBLED_PASSWORD_CHAR_LENGTH) { - mysql_mutex_unlock(&LOCK_global_system_variables); - sql_print_error("Fatal error: mysql.user table is in old format, " - "but server started with --secure-auth option."); - DBUG_RETURN(TRUE); + if (opt_secure_auth) + { + mysql_mutex_unlock(&LOCK_global_system_variables); + sql_print_error("Fatal error: mysql.user table is in old format, " + "but server started with --secure-auth option."); + DBUG_RETURN(TRUE); + } + mysql_user_table_is_in_short_password_format= true; + if (global_system_variables.old_passwords) + mysql_mutex_unlock(&LOCK_global_system_variables); + else + { + extern sys_var *Sys_old_passwords_ptr; + Sys_old_passwords_ptr->value_origin= sys_var::AUTO; + global_system_variables.old_passwords= 1; + mysql_mutex_unlock(&LOCK_global_system_variables); + sql_print_warning("mysql.user table is not updated to new password format; " + "Disabling new password usage until " + "mysql_fix_privilege_tables is run"); + } + thd->variables.old_passwords= 1; } - mysql_user_table_is_in_short_password_format= true; - if (global_system_variables.old_passwords) - mysql_mutex_unlock(&LOCK_global_system_variables); else { - extern sys_var *Sys_old_passwords_ptr; - Sys_old_passwords_ptr->value_origin= sys_var::AUTO; - global_system_variables.old_passwords= 1; + mysql_user_table_is_in_short_password_format= false; mysql_mutex_unlock(&LOCK_global_system_variables); - sql_print_warning("mysql.user table is not updated to new password format; " - "Disabling new password usage until " - "mysql_fix_privilege_tables is run"); } - thd->variables.old_passwords= 1; - } - else - { - mysql_user_table_is_in_short_password_format= false; - mysql_mutex_unlock(&LOCK_global_system_variables); } allow_all_hosts=0; @@ -1925,7 +1955,9 @@ static bool acl_load(THD *thd, const Grant_tables& tables) continue; } - char *password= get_field(&acl_memroot, user_table.password()); + char *password= const_cast<char*>(""); + if (user_table.password()) + password= get_field(&acl_memroot, user_table.password()); uint password_len= safe_strlen(password); user.auth_string.str= safe_str(password); user.auth_string.length= password_len; @@ -1978,7 +2010,7 @@ static bool acl_load(THD *thd, const Grant_tables& tables) user.user_resource.max_statement_time= 0.0; /* Starting from 4.0.2 we have more fields */ - if (user_table.num_fields() >= 31) + if (user_table.ssl_type()) { char *ssl_type=get_field(thd->mem_root, user_table.ssl_type()); if (!ssl_type) @@ -2004,14 +2036,14 @@ static bool acl_load(THD *thd, const Grant_tables& tables) user.user_resource.conn_per_hour) mqh_used=1; - if (user_table.num_fields() >= 36) + if (user_table.max_user_connections()) { /* Starting from 5.0.3 we have max_user_connections field */ ptr= get_field(thd->mem_root, user_table.max_user_connections()); user.user_resource.user_conn= ptr ? atoi(ptr) : 0; } - if (!is_role && user_table.num_fields() >= 41) + if (!is_role && user_table.plugin()) { /* We may have plugin & auth_String fields */ char *tmpstr= get_field(&acl_memroot, user_table.plugin()); @@ -2037,7 +2069,7 @@ static bool acl_load(THD *thd, const Grant_tables& tables) } } - if (user_table.num_fields() > MAX_STATEMENT_TIME_COLUMN_IDX) + if (user_table.max_statement_time()) { /* Starting from 10.1.1 we can have max_statement_time */ ptr= get_field(thd->mem_root, @@ -2067,7 +2099,7 @@ static bool acl_load(THD *thd, const Grant_tables& tables) 8, 8, MYF(0)); /* check default role, if any */ - if (!is_role && user_table.num_fields() > DEFAULT_ROLE_COLUMN_IDX) + if (!is_role && user_table.default_role()) { user.default_rolename.str= get_field(&acl_memroot, user_table.default_role()); @@ -3503,10 +3535,11 @@ int acl_set_default_role(THD *thd, const char *host, const char *user, /* update the mysql.user table with the new default role */ tables.user_table().table()->use_all_columns(); - if (tables.user_table().num_fields() <= DEFAULT_ROLE_COLUMN_IDX) + if (!tables.user_table().default_role()) { my_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, MYF(0), - table->alias.c_ptr(), DEFAULT_ROLE_COLUMN_IDX + 1, table->s->fields, + table->alias.c_ptr(), DEFAULT_ROLE_COLUMN_IDX + 1, + tables.user_table().num_fields(), static_cast<int>(table->s->mysql_version), MYSQL_VERSION_ID); mysql_mutex_unlock(&acl_cache->lock); goto end; @@ -3821,6 +3854,27 @@ bool hostname_requires_resolving(const char *hostname) } +void set_authentication_plugin_from_password(const User_table& user_table, + const char* password, + uint password_length) +{ + if (password_length == SCRAMBLED_PASSWORD_CHAR_LENGTH) + { + user_table.plugin()->store(native_password_plugin_name.str, + native_password_plugin_name.length, + system_charset_info); + } + else + { + DBUG_ASSERT(password_length == SCRAMBLED_PASSWORD_CHAR_LENGTH_323); + user_table.plugin()->store(old_password_plugin_name.str, + old_password_plugin_name.length, + system_charset_info); + } + user_table.authentication_string()->store(password, + password_length, + system_charset_info); +} /** Update record for user in mysql.user privilege table with new password. @@ -3859,7 +3913,15 @@ static bool update_user_table(THD *thd, const User_table& user_table, DBUG_RETURN(1); /* purecov: deadcode */ } store_record(table,record[1]); - user_table.password()->store(new_password, new_password_len, system_charset_info); + /* If the password column is missing, we use the + authentication_string column. */ + if (user_table.password()) + user_table.password()->store(new_password, new_password_len, system_charset_info); + else + set_authentication_plugin_from_password(user_table, new_password, + new_password_len); + + if ((error=table->file->ha_update_row(table->record[1],table->record[0])) && error != HA_ERR_RECORD_IS_THE_SAME) { @@ -3939,7 +4001,7 @@ static int replace_user_table(THD *thd, const User_table &user_table, combo.pwhash= empty_lex_str; /* if the user table is not up to date, we can't handle role updates */ - if (user_table.num_fields() <= ROLE_ASSIGN_COLUMN_IDX && handle_as_role) + if (!user_table.is_role() && handle_as_role) { my_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, MYF(0), "user", ROLE_ASSIGN_COLUMN_IDX + 1, user_table.num_fields(), @@ -4026,11 +4088,16 @@ static int replace_user_table(THD *thd, const User_table &user_table, rights= user_table.get_access(); - DBUG_PRINT("info",("table fields: %d",user_table.num_fields())); - if (combo.pwhash.str[0]) + DBUG_PRINT("info",("table fields: %d", user_table.num_fields())); + /* If we don't have a password column, we'll use the authentication_string + column later. */ + if (combo.pwhash.str[0] && user_table.password()) user_table.password()->store(combo.pwhash.str, combo.pwhash.length, system_charset_info); - if (user_table.num_fields() >= 31) /* From 4.0.0 we have more fields */ + /* We either have the password column, the plugin column, or both. Otherwise + we have a corrupt user table. */ + DBUG_ASSERT(user_table.password() || user_table.plugin()); + if (user_table.ssl_type()) /* From 4.0.0 we have more fields */ { /* We write down SSL related ACL stuff */ switch (lex->ssl_type) { @@ -4084,17 +4151,18 @@ static int replace_user_table(THD *thd, const User_table &user_table, user_table.max_updates()->store((longlong) mqh.updates, TRUE); if (mqh.specified_limits & USER_RESOURCES::CONNECTIONS_PER_HOUR) user_table.max_connections()->store((longlong) mqh.conn_per_hour, TRUE); - if (user_table.num_fields() >= 36 && + if (user_table.max_user_connections() && (mqh.specified_limits & USER_RESOURCES::USER_CONNECTIONS)) user_table.max_user_connections()->store((longlong) mqh.user_conn, FALSE); - if (user_table.num_fields() >= 41) + if (user_table.plugin()) { user_table.plugin()->set_notnull(); user_table.authentication_string()->set_notnull(); if (combo.plugin.str[0]) { DBUG_ASSERT(combo.pwhash.str[0] == 0); - user_table.password()->reset(); + if (user_table.password()) + user_table.password()->reset(); user_table.plugin()->store(combo.plugin.str, combo.plugin.length, system_charset_info); user_table.authentication_string()->store(combo.auth.str, combo.auth.length, @@ -4103,11 +4171,23 @@ static int replace_user_table(THD *thd, const User_table &user_table, if (combo.pwhash.str[0]) { DBUG_ASSERT(combo.plugin.str[0] == 0); - user_table.plugin()->reset(); - user_table.authentication_string()->reset(); + /* We have Password column. */ + if (user_table.password()) + { + user_table.plugin()->reset(); + user_table.authentication_string()->reset(); + } + else + { + /* We do not have Password column. Use PLUGIN && Authentication_string + columns instead. */ + set_authentication_plugin_from_password(user_table, + combo.pwhash.str, + combo.pwhash.length); + } } - if (user_table.num_fields() > MAX_STATEMENT_TIME_COLUMN_IDX) + if (user_table.max_statement_time()) { if (mqh.specified_limits & USER_RESOURCES::MAX_STATEMENT_TIME) user_table.max_statement_time()->store(mqh.max_statement_time); |