Commit d40acb4d authored by unknown's avatar unknown
Browse files

Use the hostname with which the user authenticated when determining which

user to update with 'SET PASSWORD = ...'. (Bug #12302)


mysql-test/r/grant2.result:
  Add new results
mysql-test/t/grant2.test:
  Add new tests
sql/set_var.cc:
  Pass priv_host into check_change_password().
sql/sql_acl.cc:
  Add exact flag for find_acl_user, so we can specify that we want
  an exact match on the hostname.
parent b977af8a
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -94,5 +94,31 @@ i
2
3
REVOKE ALL ON mysqltest_1.t1 FROM mysqltest_1@'127.0.0.0/255.0.0.0';
delete from mysql.user where user like 'mysqltest\_1';
flush privileges;
drop table mysqltest_1.t1;
grant all on mysqltest_1.* to mysqltest_1@'127.0.0.1';
select current_user();
current_user()
mysqltest_1@127.0.0.1
set password = password('changed');
select host, length(password) from mysql.user where user like 'mysqltest\_1';
host	length(password)
127.0.0.1	41
revoke all on mysqltest_1.* from mysqltest_1@'127.0.0.1';
delete from mysql.user where user like 'mysqltest\_1';
flush privileges;
grant all on mysqltest_1.* to mysqltest_1@'127.0.0.0/255.0.0.0';
select current_user();
current_user()
mysqltest_1@127.0.0.0/255.0.0.0
set password = password('changed');
select host, length(password) from mysql.user where user like 'mysqltest\_1';
host	length(password)
127.0.0.0/255.0.0.0	41
revoke all on mysqltest_1.* from mysqltest_1@'127.0.0.0/255.0.0.0';
delete from mysql.user where user like 'mysqltest\_1';
flush privileges;
drop database mysqltest_1;
set password = password("changed");
ERROR 42000: Access denied for user ''@'localhost' to database 'mysql'
+38 −0
Original line number Diff line number Diff line
@@ -122,7 +122,45 @@ select * from t1;
disconnect n1;
connection default;
REVOKE ALL ON mysqltest_1.t1 FROM mysqltest_1@'127.0.0.0/255.0.0.0';
delete from mysql.user where user like 'mysqltest\_1';
flush privileges;
drop table mysqltest_1.t1;

#
# Bug #12302: 'SET PASSWORD = ...' didn't work if connecting hostname !=
# hostname the current user is authenticated as. Note that a test for this
# was also added to the test above.
#
grant all on mysqltest_1.* to mysqltest_1@'127.0.0.1';
connect (b12302,127.0.0.1,mysqltest_1,,mysqltest_1,$MASTER_MYPORT,);
connection b12302;
select current_user();
set password = password('changed');
disconnect b12302;
connection default;
select host, length(password) from mysql.user where user like 'mysqltest\_1';
revoke all on mysqltest_1.* from mysqltest_1@'127.0.0.1';
delete from mysql.user where user like 'mysqltest\_1';
flush privileges;
grant all on mysqltest_1.* to mysqltest_1@'127.0.0.0/255.0.0.0';
connect (b12302_2,127.0.0.1,mysqltest_1,,mysqltest_1,$MASTER_MYPORT,);
connection b12302_2;
select current_user();
set password = password('changed');
disconnect b12302_2;
connection default;
select host, length(password) from mysql.user where user like 'mysqltest\_1';
revoke all on mysqltest_1.* from mysqltest_1@'127.0.0.0/255.0.0.0';
delete from mysql.user where user like 'mysqltest\_1';
flush privileges;
drop database mysqltest_1;

# But anonymous users can't change their password
connect (n5,localhost,test,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
connection n5;
--error 1044
set password = password("changed");
disconnect n5;
connection default;

# End of 4.1 tests
+12 −1
Original line number Diff line number Diff line
@@ -2944,7 +2944,18 @@ int set_var_password::check(THD *thd)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
  if (!user->host.str)
    user->host.str= (char*) thd->host_or_ip;
  {
    if (thd->priv_host != 0)
    {
      user->host.str= (char *) thd->priv_host;
      user->host.length= strlen(thd->priv_host);
    }
    else
    {
      user->host.str= (char *)"%";
      user->host.length= 1;
    }
  }
  /* Returns 1 as the function sends error to client */
  return check_change_password(thd, user->host.str, user->user.str,
                               password, strlen(password)) ? 1 : 0;
+11 −8
Original line number Diff line number Diff line
@@ -67,7 +67,8 @@ static ulong get_access(TABLE *form,uint fieldnr, uint *next_field=0);
static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b);
static ulong get_sort(uint count,...);
static void init_check_host(void);
static ACL_USER *find_acl_user(const char *host, const char *user);
static ACL_USER *find_acl_user(const char *host, const char *user,
                               my_bool exact);
static bool update_user_table(THD *thd, const char *host, const char *user,
			      const char *new_password, uint new_password_len);
static void update_hostname(acl_host_and_ip *host, const char *hostname);
@@ -1188,7 +1189,7 @@ bool check_change_password(THD *thd, const char *host, const char *user,
  }
  if (!thd->slave_thread &&
      (strcmp(thd->user,user) ||
       my_strcasecmp(&my_charset_latin1, host, thd->host_or_ip)))
       my_strcasecmp(&my_charset_latin1, host, thd->priv_host)))
  {
    if (check_access(thd, UPDATE_ACL, "mysql",0,1,0))
      return(1);
@@ -1240,7 +1241,7 @@ bool change_password(THD *thd, const char *host, const char *user,

  VOID(pthread_mutex_lock(&acl_cache->lock));
  ACL_USER *acl_user;
  if (!(acl_user= find_acl_user(host, user)))
  if (!(acl_user= find_acl_user(host, user, TRUE)))
  {
    VOID(pthread_mutex_unlock(&acl_cache->lock));
    send_error(thd, ER_PASSWORD_NO_MATCH);
@@ -1282,7 +1283,7 @@ bool change_password(THD *thd, const char *host, const char *user,
*/

static ACL_USER *
find_acl_user(const char *host, const char *user)
find_acl_user(const char *host, const char *user, my_bool exact)
{
  DBUG_ENTER("find_acl_user");
  DBUG_PRINT("enter",("host: '%s'  user: '%s'",host,user));
@@ -1298,7 +1299,9 @@ find_acl_user(const char *host, const char *user)
    if (!acl_user->user && !user[0] ||
	acl_user->user && !strcmp(user,acl_user->user))
    {
      if (compare_hostname(&acl_user->host,host,host))
      if (exact ? !my_strcasecmp(&my_charset_latin1, host,
                                 acl_user->host.hostname) :
          compare_hostname(&acl_user->host,host,host))
      {
	DBUG_RETURN(acl_user);
      }
@@ -1689,7 +1692,7 @@ static int replace_db_table(TABLE *table, const char *db,
  }

  /* Check if there is such a user in user table in memory? */
  if (!find_acl_user(combo.host.str,combo.user.str))
  if (!find_acl_user(combo.host.str,combo.user.str, FALSE))
  {
    my_error(ER_PASSWORD_NO_MATCH,MYF(0));
    DBUG_RETURN(-1);
@@ -2151,7 +2154,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
    The following should always succeed as new users are created before
    this function is called!
  */
  if (!find_acl_user(combo.host.str,combo.user.str))
  if (!find_acl_user(combo.host.str,combo.user.str, FALSE))
  {
    my_error(ER_PASSWORD_NO_MATCH,MYF(0));	/* purecov: deadcode */
    DBUG_RETURN(-1);				/* purecov: deadcode */
@@ -3448,7 +3451,7 @@ void get_privilege_desc(char *to, uint max_length, ulong access)
void get_mqh(const char *user, const char *host, USER_CONN *uc)
{
  ACL_USER *acl_user;
  if (initialized && (acl_user= find_acl_user(host,user)))
  if (initialized && (acl_user= find_acl_user(host,user, FALSE)))
    uc->user_resources= acl_user->user_resource;
  else
    bzero((char*) &uc->user_resources, sizeof(uc->user_resources));