Skip to content

Commit b814046

Browse files
committed
validate SET PASSWORD
1 parent dccd85e commit b814046

File tree

7 files changed

+114
-106
lines changed

7 files changed

+114
-106
lines changed

mysql-test/suite/plugins/r/simple_password_check.result

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,17 @@ create user foo1 identified by '123:qwe:4SD!';
9999
ERROR HY000: Your password does not satisfy the current policy requirements
100100
create user foo1 identified by '123:qwe:ASD4';
101101
ERROR HY000: Your password does not satisfy the current policy requirements
102+
create user foo1 identified by '123:qwe:ASD!';
103+
set password for foo1 = password('qwe:-23:ASD!');
104+
ERROR HY000: Your password does not satisfy the current policy requirements
105+
set password for foo1 = old_password('4we:123:ASD!');
106+
ERROR HY000: Your password does not satisfy the current policy requirements
107+
set password for foo1 = password('qwe:123:4SD!');
108+
ERROR HY000: Your password does not satisfy the current policy requirements
109+
set password for foo1 = old_password('qwe:123:ASD4');
110+
ERROR HY000: Your password does not satisfy the current policy requirements
111+
set password for foo1 = password('qwe:123:ASD!');
112+
drop user foo1;
102113
uninstall plugin simple_password_check;
103114
create user foo1 identified by 'pwd';
104115
drop user foo1;

mysql-test/suite/plugins/t/simple_password_check.test

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,18 @@ create user foo1 identified by '123:qwe:4SD!';
4848
--error ER_NOT_VALID_PASSWORD
4949
create user foo1 identified by '123:qwe:ASD4';
5050

51+
create user foo1 identified by '123:qwe:ASD!';
52+
--error ER_NOT_VALID_PASSWORD
53+
set password for foo1 = password('qwe:-23:ASD!');
54+
--error ER_NOT_VALID_PASSWORD
55+
set password for foo1 = old_password('4we:123:ASD!');
56+
--error ER_NOT_VALID_PASSWORD
57+
set password for foo1 = password('qwe:123:4SD!');
58+
--error ER_NOT_VALID_PASSWORD
59+
set password for foo1 = old_password('qwe:123:ASD4');
60+
set password for foo1 = password('qwe:123:ASD!');
61+
drop user foo1;
62+
5163
uninstall plugin simple_password_check;
5264

5365
create user foo1 identified by 'pwd';

sql/set_var.cc

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -851,10 +851,7 @@ int set_var_user::update(THD *thd)
851851
int set_var_password::check(THD *thd)
852852
{
853853
#ifndef NO_EMBEDDED_ACCESS_CHECKS
854-
user= get_current_user(thd, user);
855-
/* Returns 1 as the function sends error to client */
856-
return check_change_password(thd, user->host.str, user->user.str,
857-
password, strlen(password)) ? 1 : 0;
854+
return check_change_password(thd, user);
858855
#else
859856
return 0;
860857
#endif
@@ -863,9 +860,7 @@ int set_var_password::check(THD *thd)
863860
int set_var_password::update(THD *thd)
864861
{
865862
#ifndef NO_EMBEDDED_ACCESS_CHECKS
866-
/* Returns 1 as the function sends error to client */
867-
return change_password(thd, user->host.str, user->user.str, password) ?
868-
1 : 0;
863+
return change_password(thd, user);
869864
#else
870865
return 0;
871866
#endif

sql/set_var.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -321,10 +321,8 @@ class set_var_user: public set_var_base
321321
class set_var_password: public set_var_base
322322
{
323323
LEX_USER *user;
324-
char *password;
325324
public:
326-
set_var_password(LEX_USER *user_arg,char *password_arg)
327-
:user(user_arg), password(password_arg)
325+
set_var_password(LEX_USER *user_arg) :user(user_arg)
328326
{}
329327
int check(THD *thd);
330328
int update(THD *thd);

sql/sql_acl.cc

Lines changed: 54 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ ulong role_global_merges= 0, role_db_merges= 0, role_table_merges= 0,
349349
#endif
350350

351351
#ifndef NO_EMBEDDED_ACCESS_CHECKS
352+
static bool fix_and_copy_user(LEX_USER *to, LEX_USER *from, THD *thd);
352353
static void update_hostname(acl_host_and_ip *host, const char *hostname);
353354
static ulong get_sort(uint count,...);
354355
static bool show_proxy_grants (THD *, const char *, const char *,
@@ -965,10 +966,25 @@ static bool fix_user_plugin_ptr(ACL_USER *user)
965966

966967

967968
/*
968-
transform equivalent LEX_USER values to one:
969-
username IDENTIFIED BY PASSWORD xxx
970-
username IDENTIFIED VIA mysql_native_password USING xxx
971-
etc
969+
Validates the password, calculates password hash, transforms
970+
equivalent LEX_USER representations.
971+
972+
Upon entering this function:
973+
974+
- if user->plugin is specified, user->auth is the plugin auth data.
975+
- if user->plugin is mysql_native_password or mysql_old_password,
976+
user->auth if the password hash, and LEX_USER is transformed
977+
to match the next case (that is, user->plugin is cleared).
978+
- if user->plugin is NOT specified, built-in auth is assumed, that is
979+
mysql_native_password or mysql_old_password. In that case,
980+
user->auth is the password hash. And user->password is the original
981+
plain-text password. Either one can be set or even both.
982+
983+
Upon exiting this function:
984+
985+
- user->password is the password hash, as the mysql.user.password column
986+
- user->plugin is the plugin name, as the mysql.user.plugin column
987+
- user->auth is the plugin auth data, as the mysql.user.authentication_string column
972988
*/
973989
static bool fix_lex_user(THD *thd, LEX_USER *user)
974990
{
@@ -1005,7 +1021,7 @@ static bool fix_lex_user(THD *thd, LEX_USER *user)
10051021
}
10061022
}
10071023

1008-
if (user->password.length)
1024+
if (user->password.length && !user->auth.length)
10091025
{
10101026
size_t scramble_length;
10111027
void (*make_scramble)(char *, const char *, size_t);
@@ -2691,72 +2707,57 @@ static int check_alter_user(THD *thd, const char *host, const char *user)
26912707
Check if the user is allowed to change password
26922708
26932709
@param thd THD
2694-
@param host Hostname for the user
2695-
@param user User name
2696-
@param new_password New password
2697-
@param new_password_len The length of the new password
2698-
2699-
new_password cannot be NULL
2710+
@param user User, hostname, new password or password hash
27002711
27012712
@return Error status
27022713
@retval 0 OK
27032714
@retval 1 ERROR; In this case the error is sent to the client.
27042715
*/
27052716

2706-
int check_change_password(THD *thd, const char *host, const char *user,
2707-
char *new_password, uint new_password_len)
2717+
bool check_change_password(THD *thd, LEX_USER *user)
27082718
{
2709-
if (check_alter_user(thd, host, user))
2710-
return 1;
2719+
LEX_USER *real_user= get_current_user(thd, user);
27112720

2712-
size_t len= strlen(new_password);
2713-
if (len && len != SCRAMBLED_PASSWORD_CHAR_LENGTH &&
2714-
len != SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
2715-
{
2716-
my_error(ER_PASSWD_LENGTH, MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH);
2717-
return 1;
2718-
}
2719-
return 0;
2721+
if (fix_and_copy_user(real_user, user, thd))
2722+
return true;
2723+
2724+
*user= *real_user;
2725+
2726+
return check_alter_user(thd, user->host.str, user->user.str);
27202727
}
27212728

27222729

27232730
/**
27242731
Change a password for a user.
27252732
27262733
@param thd THD
2727-
@param host Hostname
2728-
@param user User name
2729-
@param new_password New password hash for host@user
2734+
@param user User, hostname, new password hash
27302735
27312736
@return Error code
27322737
@retval 0 ok
27332738
@retval 1 ERROR; In this case the error is sent to the client.
27342739
*/
2735-
bool change_password(THD *thd, const char *host, const char *user,
2736-
char *new_password)
2740+
bool change_password(THD *thd, LEX_USER *user)
27372741
{
27382742
TABLE_LIST tables[TABLES_MAX];
27392743
/* Buffer should be extended when password length is extended. */
27402744
char buff[512];
27412745
ulong query_length= 0;
27422746
enum_binlog_format save_binlog_format;
2743-
uint new_password_len= (uint) strlen(new_password);
27442747
int result=0;
27452748
const CSET_STRING query_save __attribute__((unused)) = thd->query_string;
27462749

27472750
DBUG_ENTER("change_password");
27482751
DBUG_PRINT("enter",("host: '%s' user: '%s' new_password: '%s'",
2749-
host,user,new_password));
2750-
DBUG_ASSERT(host != 0); // Ensured by parent
2751-
2752-
if (check_change_password(thd, host, user, new_password, new_password_len))
2753-
DBUG_RETURN(1);
2752+
user->host.str, user->user.str, user->password.str));
2753+
DBUG_ASSERT(user->host.str != 0); // Ensured by parent
27542754

27552755
if (mysql_bin_log.is_open() ||
27562756
(WSREP(thd) && !IF_WSREP(thd->wsrep_applier, 0)))
27572757
{
27582758
query_length= sprintf(buff, "SET PASSWORD FOR '%-.120s'@'%-.120s'='%-.120s'",
2759-
safe_str(user), safe_str(host), new_password);
2759+
safe_str(user->user.str), safe_str(user->host.str),
2760+
safe_str(user->password.str));
27602761
}
27612762

27622763
if (WSREP(thd) && !IF_WSREP(thd->wsrep_applier, 0))
@@ -2781,7 +2782,7 @@ bool change_password(THD *thd, const char *host, const char *user,
27812782

27822783
mysql_mutex_lock(&acl_cache->lock);
27832784
ACL_USER *acl_user;
2784-
if (!(acl_user= find_user_exact(host, user)))
2785+
if (!(acl_user= find_user_exact(user->host.str, user->user.str)))
27852786
{
27862787
mysql_mutex_unlock(&acl_cache->lock);
27872788
my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH), MYF(0));
@@ -2792,10 +2793,10 @@ bool change_password(THD *thd, const char *host, const char *user,
27922793
if (acl_user->plugin.str == native_password_plugin_name.str ||
27932794
acl_user->plugin.str == old_password_plugin_name.str)
27942795
{
2795-
acl_user->auth_string.str= strmake_root(&acl_memroot, new_password, new_password_len);
2796-
acl_user->auth_string.length= new_password_len;
2797-
set_user_salt(acl_user, new_password, new_password_len);
2798-
set_user_plugin(acl_user, new_password_len);
2796+
acl_user->auth_string.str= strmake_root(&acl_memroot, user->password.str, user->password.length);
2797+
acl_user->auth_string.length= user->password.length;
2798+
set_user_salt(acl_user, user->password.str, user->password.length);
2799+
set_user_plugin(acl_user, user->password.length);
27992800
}
28002801
else
28012802
push_warning(thd, Sql_condition::WARN_LEVEL_NOTE,
@@ -2804,7 +2805,7 @@ bool change_password(THD *thd, const char *host, const char *user,
28042805
if (update_user_table(thd, tables[USER_TABLE].table,
28052806
safe_str(acl_user->host.hostname),
28062807
safe_str(acl_user->user.str),
2807-
new_password, new_password_len))
2808+
user->password.str, user->password.length))
28082809
{
28092810
mysql_mutex_unlock(&acl_cache->lock); /* purecov: deadcode */
28102811
goto end;
@@ -5660,11 +5661,8 @@ static bool has_auth(LEX_USER *user, LEX *lex)
56605661
lex->mqh.specified_limits;
56615662
}
56625663

5663-
static bool copy_and_check_auth(LEX_USER *to, LEX_USER *from, THD *thd)
5664+
static bool fix_and_copy_user(LEX_USER *to, LEX_USER *from, THD *thd)
56645665
{
5665-
if (fix_lex_user(thd, from))
5666-
return true;
5667-
56685666
if (to != from)
56695667
{
56705668
/* preserve authentication information, if LEX_USER was reallocated */
@@ -5673,6 +5671,17 @@ static bool copy_and_check_auth(LEX_USER *to, LEX_USER *from, THD *thd)
56735671
to->auth= from->auth;
56745672
}
56755673

5674+
if (fix_lex_user(thd, to))
5675+
return true;
5676+
5677+
return false;
5678+
}
5679+
5680+
static bool copy_and_check_auth(LEX_USER *to, LEX_USER *from, THD *thd)
5681+
{
5682+
if (fix_and_copy_user(to, from, thd))
5683+
return true;
5684+
56765685
// if changing auth for an existing user
56775686
if (has_auth(to, thd->lex) && find_user_exact(to->host.str, to->user.str))
56785687
{

sql/sql_acl.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,8 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len);
206206
bool acl_getroot(Security_context *sctx, char *user, char *host,
207207
char *ip, char *db);
208208
bool acl_check_host(const char *host, const char *ip);
209-
int check_change_password(THD *thd, const char *host, const char *user,
210-
char *password, uint password_len);
211-
bool change_password(THD *thd, const char *host, const char *user,
212-
char *password);
209+
bool check_change_password(THD *thd, LEX_USER *user);
210+
bool change_password(THD *thd, LEX_USER *user);
213211

214212
bool mysql_grant_role(THD *thd, List<LEX_USER> &user_list, bool revoke);
215213
bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &user_list,

0 commit comments

Comments
 (0)