Skip to content

Commit

Permalink
parser: store the password hash in LEX_USER::auth, not in ::password
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
vuvova committed Dec 4, 2014
1 parent 91ad0cd commit 7bd9eb1
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 71 deletions.
80 changes: 37 additions & 43 deletions sql/sql_acl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -952,30 +952,33 @@ static bool fix_user_plugin_ptr(ACL_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,
native_password_plugin_name.str) == 0)
{
check_length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
}
else
if (my_strcasecmp(system_charset_info, user->plugin.str,
old_password_plugin_name.str) == 0)
{
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);
return true;
}
my_error(ER_PASSWD_LENGTH, MYF(0), check_length);
return true;
}

user->password= user->auth.length ? user->auth : null_lex_str;
user->plugin= empty_lex_str;
user->auth= empty_lex_str;
return false;
}

Expand Down Expand Up @@ -5604,8 +5607,11 @@ static bool has_auth(LEX_USER *user, LEX *lex)
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)
{
/* preserve authentication information, if LEX_USER was reallocated */
Expand All @@ -5614,14 +5620,13 @@ static bool copy_and_check_auth(LEX_USER *to, LEX_USER *from, LEX *lex)
to->auth= from->auth;
}

/*
Specifying authentication clauses forces the name to be interpreted
as a user, not a role. See also check_change_password()
*/
if (to->is_role() && has_auth(to, lex))
// if changing auth for an existing user
if (has_auth(to, thd->lex) && find_user_exact(to->host.str, to->user.str))
{
my_error(ER_PASSWORD_NO_MATCH, MYF(0));
return true;
mysql_mutex_unlock(&acl_cache->lock);
bool res= check_alter_user(thd, to->host.str, to->user.str);
mysql_mutex_lock(&acl_cache->lock);
return res;
}

return false;
Expand Down Expand Up @@ -5767,10 +5772,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
continue;
}
/* Create user if needed */
if (copy_and_check_auth(Str, tmp_Str, thd->lex))
error= -1;
else
error=replace_user_table(thd, tables[USER_TABLE].table, *Str,
error= copy_and_check_auth(Str, tmp_Str, thd) ||
replace_user_table(thd, tables[USER_TABLE].table, *Str,
0, revoke_grant, create_new_users,
MY_TEST(thd->variables.sql_mode &
MODE_NO_AUTO_CREATE_USER));
Expand Down Expand Up @@ -5943,7 +5946,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
continue;
}
/* 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,
0, revoke_grant, create_new_users,
MY_TEST(thd->variables.sql_mode &
Expand Down Expand Up @@ -6219,8 +6222,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
user_combo.host = hostname;
user_combo.user = username;

/* create the user if it does not exist */
if (copy_and_check_auth(&user_combo, &user_combo, thd->lex) ||
if (copy_and_check_auth(&user_combo, &user_combo, thd) ||
replace_user_table(thd, tables[USER_TABLE].table, user_combo, 0,
false, create_new_user,
no_auto_create_user))
Expand Down Expand Up @@ -6388,16 +6390,8 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
continue;
}

if (fix_lex_user(tmp_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,
if (copy_and_check_auth(Str, tmp_Str, thd) ||
replace_user_table(thd, tables[USER_TABLE].table, *Str,
(!db ? rights : 0), revoke_grant, create_new_users,
MY_TEST(thd->variables.sql_mode &
MODE_NO_AUTO_CREATE_USER)))
Expand Down Expand Up @@ -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->host, combo->host.str, strlen(combo->host.str));

combo->password= empty_lex_str;
combo->password= null_lex_str;
combo->plugin= empty_lex_str;
combo->auth= empty_lex_str;

Expand All @@ -10009,20 +10003,20 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
if (au->salt_len == SCRAMBLE_LENGTH)
{
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)
{
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
{
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_PASSWD_LENGTH,
ER(ER_PASSWD_LENGTH), SCRAMBLED_PASSWORD_CHAR_LENGTH);
return TRUE;
}
combo->password.str= passwd_buff;
combo->auth.str= passwd_buff;
}

if (au->plugin.str != native_password_plugin_name.str &&
Expand Down
23 changes: 0 additions & 23 deletions sql/sql_parse.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4591,29 +4591,6 @@ mysql_execute_command(THD *thd)
lex->grant & GRANT_ACL))
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)
Expand Down
10 changes: 5 additions & 5 deletions sql/sql_yacc.yy
Original file line number Diff line number Diff line change
Expand Up @@ -15534,8 +15534,8 @@ grant_user:
if (buff == NULL)
MYSQL_YYABORT;
my_make_scrambled_password_323(buff, $4.str, $4.length);
$1->password.str= buff;
$1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
$1->auth.str= buff;
$1->auth.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
}
else
{
Expand All @@ -15544,15 +15544,15 @@ grant_user:
if (buff == NULL)
MYSQL_YYABORT;
my_make_scrambled_password(buff, $4.str, $4.length);
$1->password.str= buff;
$1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
$1->auth.str= buff;
$1->auth.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
}
}
}
| user IDENTIFIED_SYM BY PASSWORD TEXT_STRING
{
$$= $1;
$1->password= $5;
$1->auth= $5;
}
| user IDENTIFIED_SYM via_or_with ident_or_text
{
Expand Down

0 comments on commit 7bd9eb1

Please sign in to comment.