Commit 7bd9eb1f authored by Sergei Golubchik's avatar Sergei Golubchik

parser: store the password hash in LEX_USER::auth, not in ::password

* indeed, "username IDENTIFIED BY PASSWORD hash" is the same
  as "username IDENTIFIED VIA mysql_native_password USING hash"
* LEX_USER::password can now be used for plain-text passwords
parent 91ad0cd5
...@@ -952,30 +952,33 @@ static bool fix_user_plugin_ptr(ACL_USER *user) ...@@ -952,30 +952,33 @@ static bool fix_user_plugin_ptr(ACL_USER *user)
*/ */
static bool fix_lex_user(LEX_USER *user) static bool fix_lex_user(LEX_USER *user)
{ {
size_t check_length= 0; size_t check_length;
if (my_strcasecmp(system_charset_info, user->plugin.str, if (my_strcasecmp(system_charset_info, user->plugin.str,
native_password_plugin_name.str) == 0) native_password_plugin_name.str) == 0)
{
check_length= SCRAMBLED_PASSWORD_CHAR_LENGTH; check_length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
}
else else
if (my_strcasecmp(system_charset_info, user->plugin.str, if (my_strcasecmp(system_charset_info, user->plugin.str,
old_password_plugin_name.str) == 0) old_password_plugin_name.str) == 0)
{
check_length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; check_length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
} else
if (user->plugin.length)
return false; // nothing else to do
else
if (user->auth.length == SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
check_length= 0; // length is valid, no need to re-check
else
check_length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
if (check_length) if (check_length && user->auth.length && user->auth.length != check_length)
{
user->password= user->auth.length ? user->auth : null_lex_str;
user->plugin= empty_lex_str;
user->auth= empty_lex_str;
if (user->password.length && user->password.length != check_length)
{ {
my_error(ER_PASSWD_LENGTH, MYF(0), check_length); my_error(ER_PASSWD_LENGTH, MYF(0), check_length);
return true; return true;
} }
}
user->password= user->auth.length ? user->auth : null_lex_str;
user->plugin= empty_lex_str;
user->auth= empty_lex_str;
return false; return false;
} }
...@@ -5604,8 +5607,11 @@ static bool has_auth(LEX_USER *user, LEX *lex) ...@@ -5604,8 +5607,11 @@ static bool has_auth(LEX_USER *user, LEX *lex)
lex->mqh.specified_limits; lex->mqh.specified_limits;
} }
static bool copy_and_check_auth(LEX_USER *to, LEX_USER *from, LEX *lex) static bool copy_and_check_auth(LEX_USER *to, LEX_USER *from, THD *thd)
{ {
if (fix_lex_user(from))
return true;
if (to != from) if (to != from)
{ {
/* preserve authentication information, if LEX_USER was reallocated */ /* preserve authentication information, if LEX_USER was reallocated */
...@@ -5614,14 +5620,13 @@ static bool copy_and_check_auth(LEX_USER *to, LEX_USER *from, LEX *lex) ...@@ -5614,14 +5620,13 @@ static bool copy_and_check_auth(LEX_USER *to, LEX_USER *from, LEX *lex)
to->auth= from->auth; to->auth= from->auth;
} }
/* // if changing auth for an existing user
Specifying authentication clauses forces the name to be interpreted if (has_auth(to, thd->lex) && find_user_exact(to->host.str, to->user.str))
as a user, not a role. See also check_change_password()
*/
if (to->is_role() && has_auth(to, lex))
{ {
my_error(ER_PASSWORD_NO_MATCH, MYF(0)); mysql_mutex_unlock(&acl_cache->lock);
return true; bool res= check_alter_user(thd, to->host.str, to->user.str);
mysql_mutex_lock(&acl_cache->lock);
return res;
} }
return false; return false;
...@@ -5767,10 +5772,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, ...@@ -5767,10 +5772,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
continue; continue;
} }
/* Create user if needed */ /* Create user if needed */
if (copy_and_check_auth(Str, tmp_Str, thd->lex)) error= copy_and_check_auth(Str, tmp_Str, thd) ||
error= -1; replace_user_table(thd, tables[USER_TABLE].table, *Str,
else
error=replace_user_table(thd, tables[USER_TABLE].table, *Str,
0, revoke_grant, create_new_users, 0, revoke_grant, create_new_users,
MY_TEST(thd->variables.sql_mode & MY_TEST(thd->variables.sql_mode &
MODE_NO_AUTO_CREATE_USER)); MODE_NO_AUTO_CREATE_USER));
...@@ -5943,7 +5946,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, ...@@ -5943,7 +5946,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
continue; continue;
} }
/* Create user if needed */ /* Create user if needed */
if (copy_and_check_auth(Str, tmp_Str, thd->lex) || if (copy_and_check_auth(Str, tmp_Str, thd) ||
replace_user_table(thd, tables[USER_TABLE].table, *Str, replace_user_table(thd, tables[USER_TABLE].table, *Str,
0, revoke_grant, create_new_users, 0, revoke_grant, create_new_users,
MY_TEST(thd->variables.sql_mode & MY_TEST(thd->variables.sql_mode &
...@@ -6219,8 +6222,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke) ...@@ -6219,8 +6222,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
user_combo.host = hostname; user_combo.host = hostname;
user_combo.user = username; user_combo.user = username;
/* create the user if it does not exist */ if (copy_and_check_auth(&user_combo, &user_combo, thd) ||
if (copy_and_check_auth(&user_combo, &user_combo, thd->lex) ||
replace_user_table(thd, tables[USER_TABLE].table, user_combo, 0, replace_user_table(thd, tables[USER_TABLE].table, user_combo, 0,
false, create_new_user, false, create_new_user,
no_auto_create_user)) no_auto_create_user))
...@@ -6388,16 +6390,8 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, ...@@ -6388,16 +6390,8 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
continue; continue;
} }
if (fix_lex_user(tmp_Str)) if (copy_and_check_auth(Str, tmp_Str, thd) ||
{ replace_user_table(thd, tables[USER_TABLE].table, *Str,
result= TRUE;
continue;
}
if (copy_and_check_auth(Str, tmp_Str, thd->lex))
result= true;
else
if (replace_user_table(thd, tables[USER_TABLE].table, *Str,
(!db ? rights : 0), revoke_grant, create_new_users, (!db ? rights : 0), revoke_grant, create_new_users,
MY_TEST(thd->variables.sql_mode & MY_TEST(thd->variables.sql_mode &
MODE_NO_AUTO_CREATE_USER))) MODE_NO_AUTO_CREATE_USER)))
...@@ -9998,7 +9992,7 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, ...@@ -9998,7 +9992,7 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
thd->make_lex_string(&combo->user, combo->user.str, strlen(combo->user.str)); thd->make_lex_string(&combo->user, combo->user.str, strlen(combo->user.str));
thd->make_lex_string(&combo->host, combo->host.str, strlen(combo->host.str)); thd->make_lex_string(&combo->host, combo->host.str, strlen(combo->host.str));
combo->password= empty_lex_str; combo->password= null_lex_str;
combo->plugin= empty_lex_str; combo->plugin= empty_lex_str;
combo->auth= empty_lex_str; combo->auth= empty_lex_str;
...@@ -10009,12 +10003,12 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, ...@@ -10009,12 +10003,12 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
if (au->salt_len == SCRAMBLE_LENGTH) if (au->salt_len == SCRAMBLE_LENGTH)
{ {
make_password_from_salt(passwd_buff, au->salt); make_password_from_salt(passwd_buff, au->salt);
combo->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH; combo->auth.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
} }
else if (au->salt_len == SCRAMBLE_LENGTH_323) else if (au->salt_len == SCRAMBLE_LENGTH_323)
{ {
make_password_from_salt_323(passwd_buff, (ulong *) au->salt); make_password_from_salt_323(passwd_buff, (ulong *) au->salt);
combo->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; combo->auth.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
} }
else else
{ {
...@@ -10022,7 +10016,7 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, ...@@ -10022,7 +10016,7 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
ER(ER_PASSWD_LENGTH), SCRAMBLED_PASSWORD_CHAR_LENGTH); ER(ER_PASSWD_LENGTH), SCRAMBLED_PASSWORD_CHAR_LENGTH);
return TRUE; return TRUE;
} }
combo->password.str= passwd_buff; combo->auth.str= passwd_buff;
} }
if (au->plugin.str != native_password_plugin_name.str && if (au->plugin.str != native_password_plugin_name.str &&
......
...@@ -4591,29 +4591,6 @@ mysql_execute_command(THD *thd) ...@@ -4591,29 +4591,6 @@ mysql_execute_command(THD *thd)
lex->grant & GRANT_ACL)) lex->grant & GRANT_ACL))
goto error; goto error;
} }
else if (user->password.str)
{
// Are we trying to change a password of another user?
const char *hostname= user->host.str, *username=user->user.str;
bool userok;
if (username == current_user.str)
{
username= thd->security_ctx->priv_user;
hostname= thd->security_ctx->priv_host;
userok= true;
}
else
{
if (!hostname)
hostname= host_not_specified.str;
userok= is_acl_user(hostname, username);
}
if (userok && check_change_password (thd, hostname, username,
user->password.str,
user->password.length))
goto error;
}
} }
} }
if (first_table) if (first_table)
......
...@@ -15534,8 +15534,8 @@ grant_user: ...@@ -15534,8 +15534,8 @@ grant_user:
if (buff == NULL) if (buff == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
my_make_scrambled_password_323(buff, $4.str, $4.length); my_make_scrambled_password_323(buff, $4.str, $4.length);
$1->password.str= buff; $1->auth.str= buff;
$1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; $1->auth.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
} }
else else
{ {
...@@ -15544,15 +15544,15 @@ grant_user: ...@@ -15544,15 +15544,15 @@ grant_user:
if (buff == NULL) if (buff == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
my_make_scrambled_password(buff, $4.str, $4.length); my_make_scrambled_password(buff, $4.str, $4.length);
$1->password.str= buff; $1->auth.str= buff;
$1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH; $1->auth.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
} }
} }
} }
| user IDENTIFIED_SYM BY PASSWORD TEXT_STRING | user IDENTIFIED_SYM BY PASSWORD TEXT_STRING
{ {
$$= $1; $$= $1;
$1->password= $5; $1->auth= $5;
} }
| user IDENTIFIED_SYM via_or_with ident_or_text | user IDENTIFIED_SYM via_or_with ident_or_text
{ {
......
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