cleanup: sql_acl.cc password->LEX_CSTRING

This commit is contained in:
Sergei Golubchik 2018-10-12 18:48:15 +02:00
parent ca7401afdf
commit 3476854013

View File

@ -119,13 +119,10 @@ public:
char *db; char *db;
}; };
class ACL_USER_BASE :public ACL_ACCESS class ACL_USER_BASE :public ACL_ACCESS, public Sql_alloc
{ {
public: public:
static void *operator new(size_t size, MEM_ROOT *mem_root)
{ return (void*) alloc_root(mem_root, size); }
static void operator delete(void *, MEM_ROOT *){}
uchar flags; // field used to store various state information uchar flags; // field used to store various state information
LEX_CSTRING user; LEX_CSTRING user;
/* list to hold references to granted roles (ACL_ROLE instances) */ /* list to hold references to granted roles (ACL_ROLE instances) */
@ -620,8 +617,8 @@ static ACL_USER *find_user_wild(const char *host, const char *user, const char *
static ACL_ROLE *find_acl_role(const char *user); static ACL_ROLE *find_acl_role(const char *user);
static ROLE_GRANT_PAIR *find_role_grant_pair(const LEX_CSTRING *u, const LEX_CSTRING *h, const LEX_CSTRING *r); static ROLE_GRANT_PAIR *find_role_grant_pair(const LEX_CSTRING *u, const LEX_CSTRING *h, const LEX_CSTRING *r);
static ACL_USER_BASE *find_acl_user_base(const char *user, const char *host); static ACL_USER_BASE *find_acl_user_base(const char *user, const char *host);
static bool update_user_table(THD *, const User_table &, const char *, const char *, const static bool update_user_table(THD *, const User_table &, const char *,
char *, size_t new_password_len); const char *, const LEX_CSTRING &);
static bool acl_load(THD *thd, const Grant_tables& grant_tables); static bool acl_load(THD *thd, const Grant_tables& grant_tables);
static inline void get_grantor(THD *thd, char* grantor); static inline void get_grantor(THD *thd, char* grantor);
static bool add_role_user_mapping(const char *uname, const char *hname, const char *rname); static bool add_role_user_mapping(const char *uname, const char *hname, const char *rname);
@ -1427,24 +1424,23 @@ static bool validate_password(LEX_USER *user, THD *thd)
Binary form is stored in user.salt. Binary form is stored in user.salt.
@param acl_user The object where to store the salt @param acl_user The object where to store the salt
@param password The password hash containing the salt @param password The password hash
@param password_len The length of the password hash
Despite the name of the function it is used when loading ACLs from disk Despite the name of the function it is used when loading ACLs from disk
to store the password hash in the ACL_USER object. to store the password hash in the ACL_USER object.
*/ */
static void static void
set_user_salt(ACL_USER *acl_user, const char *password, size_t password_len) set_user_salt(ACL_USER *acl_user, const LEX_CSTRING &password)
{ {
if (password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH) if (password.length == SCRAMBLED_PASSWORD_CHAR_LENGTH)
{ {
get_salt_from_password(acl_user->salt, password); get_salt_from_password(acl_user->salt, password.str);
acl_user->salt_len= SCRAMBLE_LENGTH; acl_user->salt_len= SCRAMBLE_LENGTH;
} }
else if (password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH_323) else if (password.length == SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
{ {
get_salt_from_password_323((ulong *) acl_user->salt, password); get_salt_from_password_323((ulong *) acl_user->salt, password.str);
acl_user->salt_len= SCRAMBLE_LENGTH_323; acl_user->salt_len= SCRAMBLE_LENGTH_323;
} }
else else
@ -1487,8 +1483,7 @@ static bool fix_user_plugin_ptr(ACL_USER *user)
else else
return true; return true;
if (user->auth_string.length) set_user_salt(user, user->auth_string);
set_user_salt(user, user->auth_string.str, user->auth_string.length);
return false; return false;
} }
@ -1699,7 +1694,6 @@ static bool acl_load(THD *thd, const Grant_tables& tables)
READ_RECORD read_record_info; READ_RECORD read_record_info;
bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE; bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE;
char tmp_name[SAFE_NAME_LEN+1]; char tmp_name[SAFE_NAME_LEN+1];
int password_length;
Sql_mode_save old_mode_save(thd); Sql_mode_save old_mode_save(thd);
DBUG_ENTER("acl_load"); DBUG_ENTER("acl_load");
@ -1772,8 +1766,8 @@ static bool acl_load(THD *thd, const Grant_tables& tables)
USERNAME_CHAR_LENGTH); USERNAME_CHAR_LENGTH);
if (user_table.password()) // Password column might be missing. (MySQL 5.7.6+) if (user_table.password()) // Password column might be missing. (MySQL 5.7.6+)
{ {
password_length= user_table.password()->field_length / int password_length= user_table.password()->field_length /
user_table.password()->charset()->mbmaxlen; user_table.password()->charset()->mbmaxlen;
if (password_length < SCRAMBLED_PASSWORD_CHAR_LENGTH_323) if (password_length < SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
{ {
sql_print_error("Fatal error: mysql.user table is damaged or in " sql_print_error("Fatal error: mysql.user table is damaged or in "
@ -1849,111 +1843,113 @@ static bool acl_load(THD *thd, const Grant_tables& tables)
continue; continue;
} }
char *password= const_cast<char*>(""); LEX_CSTRING password= empty_clex_str;
if (user_table.password()) if (user_table.password())
password= get_field(&acl_memroot, user_table.password()); {
size_t password_len= safe_strlen(password); password.str= get_field(&acl_memroot, user_table.password());
user.auth_string.str= safe_str(password); password.length= safe_strlen(password.str);
user.auth_string.length= password_len; }
set_user_salt(&user, password, password_len); user.auth_string= password;
set_user_salt(&user, password);
if (!is_role && set_user_plugin(&user, password_len)) if (!is_role && set_user_plugin(&user, password.length))
continue; continue;
user.access= user_table.get_access() & GLOBAL_ACLS;
/*
if it is pre 5.0.1 privilege table then map CREATE privilege on
CREATE VIEW & SHOW VIEW privileges
*/
if (user_table.num_fields() <= 31 && (user.access & CREATE_ACL))
user.access|= (CREATE_VIEW_ACL | SHOW_VIEW_ACL);
/*
if it is pre 5.0.2 privilege table then map CREATE/ALTER privilege on
CREATE PROCEDURE & ALTER PROCEDURE privileges
*/
if (user_table.num_fields() <= 33 && (user.access & CREATE_ACL))
user.access|= CREATE_PROC_ACL;
if (user_table.num_fields() <= 33 && (user.access & ALTER_ACL))
user.access|= ALTER_PROC_ACL;
/*
pre 5.0.3 did not have CREATE_USER_ACL
*/
if (user_table.num_fields() <= 36 && (user.access & GRANT_ACL))
user.access|= CREATE_USER_ACL;
/*
if it is pre 5.1.6 privilege table then map CREATE privilege on
CREATE|ALTER|DROP|EXECUTE EVENT
*/
if (user_table.num_fields() <= 37 && (user.access & SUPER_ACL))
user.access|= EVENT_ACL;
/*
if it is pre 5.1.6 privilege then map TRIGGER privilege on CREATE.
*/
if (user_table.num_fields() <= 38 && (user.access & SUPER_ACL))
user.access|= TRIGGER_ACL;
if (user_table.num_fields() <= 46 && (user.access & DELETE_ACL))
user.access|= DELETE_HISTORY_ACL;
user.sort= get_sort(2, user.host.hostname, user.user.str);
user.hostname_length= safe_strlen(user.host.hostname);
user.user_resource.user_conn= 0;
user.user_resource.max_statement_time= 0.0;
/* Starting from 4.0.2 we have more fields */
if (user_table.ssl_type())
{ {
user.access= user_table.get_access() & GLOBAL_ACLS; char *ssl_type=get_field(thd->mem_root, user_table.ssl_type());
/* if (!ssl_type)
if it is pre 5.0.1 privilege table then map CREATE privilege on user.ssl_type=SSL_TYPE_NONE;
CREATE VIEW & SHOW VIEW privileges else if (!strcmp(ssl_type, "ANY"))
*/ user.ssl_type=SSL_TYPE_ANY;
if (user_table.num_fields() <= 31 && (user.access & CREATE_ACL)) else if (!strcmp(ssl_type, "X509"))
user.access|= (CREATE_VIEW_ACL | SHOW_VIEW_ACL); user.ssl_type=SSL_TYPE_X509;
else /* !strcmp(ssl_type, "SPECIFIED") */
user.ssl_type=SSL_TYPE_SPECIFIED;
/* user.ssl_cipher= get_field(&acl_memroot, user_table.ssl_cipher());
if it is pre 5.0.2 privilege table then map CREATE/ALTER privilege on user.x509_issuer= get_field(&acl_memroot, user_table.x509_issuer());
CREATE PROCEDURE & ALTER PROCEDURE privileges user.x509_subject= get_field(&acl_memroot, user_table.x509_subject());
*/
if (user_table.num_fields() <= 33 && (user.access & CREATE_ACL))
user.access|= CREATE_PROC_ACL;
if (user_table.num_fields() <= 33 && (user.access & ALTER_ACL))
user.access|= ALTER_PROC_ACL;
/* char *ptr = get_field(thd->mem_root, user_table.max_questions());
pre 5.0.3 did not have CREATE_USER_ACL user.user_resource.questions=ptr ? atoi(ptr) : 0;
*/ ptr = get_field(thd->mem_root, user_table.max_updates());
if (user_table.num_fields() <= 36 && (user.access & GRANT_ACL)) user.user_resource.updates=ptr ? atoi(ptr) : 0;
user.access|= CREATE_USER_ACL; ptr = get_field(thd->mem_root, user_table.max_connections());
user.user_resource.conn_per_hour= ptr ? atoi(ptr) : 0;
if (user.user_resource.questions || user.user_resource.updates ||
user.user_resource.conn_per_hour)
mqh_used=1;
if (user_table.max_user_connections())
/*
if it is pre 5.1.6 privilege table then map CREATE privilege on
CREATE|ALTER|DROP|EXECUTE EVENT
*/
if (user_table.num_fields() <= 37 && (user.access & SUPER_ACL))
user.access|= EVENT_ACL;
/*
if it is pre 5.1.6 privilege then map TRIGGER privilege on CREATE.
*/
if (user_table.num_fields() <= 38 && (user.access & SUPER_ACL))
user.access|= TRIGGER_ACL;
if (user_table.num_fields() <= 46 && (user.access & DELETE_ACL))
user.access|= DELETE_HISTORY_ACL;
user.sort= get_sort(2, user.host.hostname, user.user.str);
user.hostname_length= safe_strlen(user.host.hostname);
user.user_resource.user_conn= 0;
user.user_resource.max_statement_time= 0.0;
/* Starting from 4.0.2 we have more fields */
if (user_table.ssl_type())
{ {
char *ssl_type=get_field(thd->mem_root, user_table.ssl_type()); /* Starting from 5.0.3 we have max_user_connections field */
if (!ssl_type) ptr= get_field(thd->mem_root, user_table.max_user_connections());
user.ssl_type=SSL_TYPE_NONE; user.user_resource.user_conn= ptr ? atoi(ptr) : 0;
else if (!strcmp(ssl_type, "ANY")) }
user.ssl_type=SSL_TYPE_ANY;
else if (!strcmp(ssl_type, "X509"))
user.ssl_type=SSL_TYPE_X509;
else /* !strcmp(ssl_type, "SPECIFIED") */
user.ssl_type=SSL_TYPE_SPECIFIED;
user.ssl_cipher= get_field(&acl_memroot, user_table.ssl_cipher()); if (!is_role && user_table.plugin())
user.x509_issuer= get_field(&acl_memroot, user_table.x509_issuer()); {
user.x509_subject= get_field(&acl_memroot, user_table.x509_subject()); /* We may have plugin & auth_string fields */
char *tmpstr= get_field(&acl_memroot, user_table.plugin());
char *ptr = get_field(thd->mem_root, user_table.max_questions()); if (tmpstr)
user.user_resource.questions=ptr ? atoi(ptr) : 0;
ptr = get_field(thd->mem_root, user_table.max_updates());
user.user_resource.updates=ptr ? atoi(ptr) : 0;
ptr = get_field(thd->mem_root, user_table.max_connections());
user.user_resource.conn_per_hour= ptr ? atoi(ptr) : 0;
if (user.user_resource.questions || user.user_resource.updates ||
user.user_resource.conn_per_hour)
mqh_used=1;
if (user_table.max_user_connections())
{ {
/* Starting from 5.0.3 we have max_user_connections field */ user.plugin.str= tmpstr;
ptr= get_field(thd->mem_root, user_table.max_user_connections()); user.plugin.length= strlen(user.plugin.str);
user.user_resource.user_conn= ptr ? atoi(ptr) : 0; user.auth_string.str=
} safe_str(get_field(&acl_memroot,
user_table.authentication_string()));
user.auth_string.length= strlen(user.auth_string.str);
if (!is_role && user_table.plugin()) if (password.length)
{
/* We may have plugin & auth_String fields */
char *tmpstr= get_field(&acl_memroot, user_table.plugin());
if (tmpstr)
{ {
user.plugin.str= tmpstr; if (user.auth_string.length)
user.plugin.length= strlen(user.plugin.str);
user.auth_string.str=
safe_str(get_field(&acl_memroot,
user_table.authentication_string()));
user.auth_string.length= strlen(user.auth_string.str);
if (user.auth_string.length && password_len)
{ {
sql_print_warning("'user' entry '%s@%s' has both a password " sql_print_warning("'user' entry '%s@%s' has both a password "
"and an authentication plugin specified. The " "and an authentication plugin specified. The "
@ -1961,68 +1957,70 @@ static bool acl_load(THD *thd, const Grant_tables& tables)
safe_str(user.user.str), safe_str(user.user.str),
safe_str(user.host.hostname)); safe_str(user.host.hostname));
} }
else
fix_user_plugin_ptr(&user); user.auth_string= password;
} }
}
if (user_table.max_statement_time()) fix_user_plugin_ptr(&user);
{
/* Starting from 10.1.1 we can have max_statement_time */
ptr= get_field(thd->mem_root,
user_table.max_statement_time());
user.user_resource.max_statement_time= ptr ? atof(ptr) : 0.0;
} }
} }
else
{
user.ssl_type=SSL_TYPE_NONE;
#ifndef TO_BE_REMOVED
if (user_table.num_fields() <= 13)
{ // Without grant
if (user.access & CREATE_ACL)
user.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL;
}
/* Convert old privileges */
user.access|= LOCK_TABLES_ACL | CREATE_TMP_ACL | SHOW_DB_ACL;
if (user.access & FILE_ACL)
user.access|= REPL_CLIENT_ACL | REPL_SLAVE_ACL;
if (user.access & PROCESS_ACL)
user.access|= SUPER_ACL | EXECUTE_ACL;
#endif
}
(void) my_init_dynamic_array(&user.role_grants,sizeof(ACL_ROLE *), if (user_table.max_statement_time())
8, 8, MYF(0));
/* check default role, if any */
if (!is_role && user_table.default_role())
{ {
user.default_rolename.str= /* Starting from 10.1.1 we can have max_statement_time */
get_field(&acl_memroot, user_table.default_role()); ptr= get_field(thd->mem_root,
user.default_rolename.length= safe_strlen(user.default_rolename.str); user_table.max_statement_time());
user.user_resource.max_statement_time= ptr ? atof(ptr) : 0.0;
} }
if (is_role)
{
DBUG_PRINT("info", ("Found role %s", user.user.str));
ACL_ROLE *entry= new (&acl_memroot) ACL_ROLE(&user, &acl_memroot);
entry->role_grants = user.role_grants;
(void) my_init_dynamic_array(&entry->parent_grantee,
sizeof(ACL_USER_BASE *), 8, 8, MYF(0));
my_hash_insert(&acl_roles, (uchar *)entry);
continue;
}
else
{
DBUG_PRINT("info", ("Found user %s", user.user.str));
(void) push_dynamic(&acl_users,(uchar*) &user);
}
if (!user.host.hostname ||
(user.host.hostname[0] == wild_many && !user.host.hostname[1]))
allow_all_hosts=1; // Anyone can connect
} }
else
{
user.ssl_type=SSL_TYPE_NONE;
#ifndef TO_BE_REMOVED
if (user_table.num_fields() <= 13)
{ // Without grant
if (user.access & CREATE_ACL)
user.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL;
}
/* Convert old privileges */
user.access|= LOCK_TABLES_ACL | CREATE_TMP_ACL | SHOW_DB_ACL;
if (user.access & FILE_ACL)
user.access|= REPL_CLIENT_ACL | REPL_SLAVE_ACL;
if (user.access & PROCESS_ACL)
user.access|= SUPER_ACL | EXECUTE_ACL;
#endif
}
(void) my_init_dynamic_array(&user.role_grants,sizeof(ACL_ROLE *),
8, 8, MYF(0));
/* check default role, if any */
if (!is_role && user_table.default_role())
{
user.default_rolename.str=
get_field(&acl_memroot, user_table.default_role());
user.default_rolename.length= safe_strlen(user.default_rolename.str);
}
if (is_role)
{
DBUG_PRINT("info", ("Found role %s", user.user.str));
ACL_ROLE *entry= new (&acl_memroot) ACL_ROLE(&user, &acl_memroot);
entry->role_grants = user.role_grants;
(void) my_init_dynamic_array(&entry->parent_grantee,
sizeof(ACL_USER_BASE *), 8, 8, MYF(0));
my_hash_insert(&acl_roles, (uchar *)entry);
continue;
}
else
{
DBUG_PRINT("info", ("Found user %s", user.user.str));
(void) push_dynamic(&acl_users,(uchar*) &user);
}
if (!user.host.hostname ||
(user.host.hostname[0] == wild_many && !user.host.hostname[1]))
allow_all_hosts=1; // Anyone can connect
} }
my_qsort((uchar*) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements, my_qsort((uchar*) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements,
sizeof(ACL_USER),(qsort_cmp) acl_compare); sizeof(ACL_USER),(qsort_cmp) acl_compare);
@ -2604,38 +2602,31 @@ static void acl_update_role(const char *rolename, ulong privileges)
} }
static void acl_update_user(const char *user, const char *host, static void acl_update_user(const LEX_USER &combo, enum SSL_type ssl_type,
const char *password, size_t password_len, const char *ssl_cipher, const char *x509_issuer,
enum SSL_type ssl_type, const char *x509_subject, USER_RESOURCES *mqh,
const char *ssl_cipher, ulong privileges)
const char *x509_issuer,
const char *x509_subject,
USER_RESOURCES *mqh,
ulong privileges,
const LEX_CSTRING *plugin,
const LEX_CSTRING *auth)
{ {
mysql_mutex_assert_owner(&acl_cache->lock); mysql_mutex_assert_owner(&acl_cache->lock);
for (uint i=0 ; i < acl_users.elements ; i++) for (uint i=0 ; i < acl_users.elements ; i++)
{ {
ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*); ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*);
if (acl_user->eq(user, host)) if (acl_user->eq(combo.user.str, combo.host.str))
{ {
if (plugin->str[0]) if (combo.plugin.str[0])
{ {
acl_user->plugin= *plugin; acl_user->plugin= combo.plugin;
acl_user->auth_string= safe_lexcstrdup_root(&acl_memroot, *auth); acl_user->auth_string= safe_lexcstrdup_root(&acl_memroot, combo.auth);
if (fix_user_plugin_ptr(acl_user)) if (fix_user_plugin_ptr(acl_user))
acl_user->plugin= safe_lexcstrdup_root(&acl_memroot, *plugin); acl_user->plugin= safe_lexcstrdup_root(&acl_memroot, combo.plugin);
} }
else else
if (password[0]) if (combo.pwhash.length)
{ {
acl_user->auth_string.str= strmake_root(&acl_memroot, password, password_len); acl_user->auth_string= safe_lexcstrdup_root(&acl_memroot, combo.pwhash);
acl_user->auth_string.length= password_len; set_user_salt(acl_user, combo.pwhash);
set_user_salt(acl_user, password, password_len); set_user_plugin(acl_user, combo.pwhash.length);
set_user_plugin(acl_user, password_len);
} }
acl_user->access=privileges; acl_user->access=privileges;
if (mqh->specified_limits & USER_RESOURCES::QUERIES_PER_HOUR) if (mqh->specified_limits & USER_RESOURCES::QUERIES_PER_HOUR)
@ -2680,45 +2671,39 @@ static void acl_insert_role(const char *rolename, ulong privileges)
} }
static void acl_insert_user(const char *user, const char *host, static void acl_insert_user(const LEX_USER &combo, enum SSL_type ssl_type,
const char *password, size_t password_len, const char *ssl_cipher, const char *x509_issuer,
enum SSL_type ssl_type, const char *x509_subject, USER_RESOURCES *mqh,
const char *ssl_cipher, ulong privileges)
const char *x509_issuer,
const char *x509_subject,
USER_RESOURCES *mqh,
ulong privileges,
const LEX_CSTRING *plugin,
const LEX_CSTRING *auth)
{ {
ACL_USER acl_user; ACL_USER acl_user;
mysql_mutex_assert_owner(&acl_cache->lock); mysql_mutex_assert_owner(&acl_cache->lock);
bzero(&acl_user, sizeof(acl_user)); bzero(&acl_user, sizeof(acl_user));
acl_user.user.str=*user ? strdup_root(&acl_memroot,user) : 0; acl_user.user= safe_lexcstrdup_root(&acl_memroot, combo.user);
acl_user.user.length= strlen(user); if (!acl_user.user.length)
update_hostname(&acl_user.host, safe_strdup_root(&acl_memroot, host)); acl_user.user.str= NULL; // the rest of the code expects that XXX
if (plugin->str[0]) update_hostname(&acl_user.host, safe_strdup_root(&acl_memroot, combo.host.str));
if (combo.plugin.str[0])
{ {
acl_user.plugin= *plugin; acl_user.plugin= combo.plugin;
acl_user.auth_string= safe_lexcstrdup_root(&acl_memroot, *auth); acl_user.auth_string= safe_lexcstrdup_root(&acl_memroot, combo.auth);
if (fix_user_plugin_ptr(&acl_user)) if (fix_user_plugin_ptr(&acl_user))
acl_user.plugin= safe_lexcstrdup_root(&acl_memroot, *plugin); acl_user.plugin= safe_lexcstrdup_root(&acl_memroot, combo.plugin);
} }
else else
{ {
acl_user.auth_string.str= strmake_root(&acl_memroot, password, password_len); acl_user.auth_string= safe_lexcstrdup_root(&acl_memroot, combo.pwhash);
acl_user.auth_string.length= password_len; set_user_salt(&acl_user, combo.pwhash);
set_user_salt(&acl_user, password, password_len); set_user_plugin(&acl_user, combo.pwhash.length);
set_user_plugin(&acl_user, password_len);
} }
acl_user.flags= 0; acl_user.flags= 0;
acl_user.access=privileges; acl_user.access=privileges;
acl_user.user_resource = *mqh; acl_user.user_resource = *mqh;
acl_user.sort=get_sort(2, acl_user.host.hostname, acl_user.user.str); acl_user.sort=get_sort(2, acl_user.host.hostname, acl_user.user.str);
acl_user.hostname_length=(uint) strlen(host); acl_user.hostname_length= combo.host.length;
acl_user.ssl_type= (ssl_type != SSL_TYPE_NOT_SPECIFIED ? acl_user.ssl_type= (ssl_type != SSL_TYPE_NOT_SPECIFIED ?
ssl_type : SSL_TYPE_NONE); ssl_type : SSL_TYPE_NONE);
acl_user.ssl_cipher= ssl_cipher ? strdup_root(&acl_memroot,ssl_cipher) : 0; acl_user.ssl_cipher= ssl_cipher ? strdup_root(&acl_memroot,ssl_cipher) : 0;
@ -3293,7 +3278,7 @@ bool change_password(THD *thd, LEX_USER *user)
acl_user->plugin.str == old_password_plugin_name.str) acl_user->plugin.str == old_password_plugin_name.str)
{ {
acl_user->auth_string= safe_lexcstrdup_root(&acl_memroot, user->pwhash); acl_user->auth_string= safe_lexcstrdup_root(&acl_memroot, user->pwhash);
set_user_salt(acl_user, user->pwhash.str, user->pwhash.length); set_user_salt(acl_user, user->pwhash);
set_user_plugin(acl_user, user->pwhash.length); set_user_plugin(acl_user, user->pwhash.length);
} }
@ -3304,8 +3289,7 @@ bool change_password(THD *thd, LEX_USER *user)
if (update_user_table(thd, tables.user_table(), if (update_user_table(thd, tables.user_table(),
safe_str(acl_user->host.hostname), safe_str(acl_user->host.hostname),
safe_str(acl_user->user.str), safe_str(acl_user->user.str), user->pwhash))
user->pwhash.str, user->pwhash.length))
{ {
mysql_mutex_unlock(&acl_cache->lock); /* purecov: deadcode */ mysql_mutex_unlock(&acl_cache->lock); /* purecov: deadcode */
goto end; goto end;
@ -3757,11 +3741,11 @@ bool hostname_requires_resolving(const char *hostname)
} }
void set_authentication_plugin_from_password(const User_table& user_table, static void set_plugin_from_password(const User_table& user_table,
const char* password, size_t password_length) const LEX_CSTRING& password)
{ {
if (password_length == SCRAMBLED_PASSWORD_CHAR_LENGTH || if (password.length == SCRAMBLED_PASSWORD_CHAR_LENGTH ||
password_length == 0) password.length == 0)
{ {
user_table.plugin()->store(native_password_plugin_name.str, user_table.plugin()->store(native_password_plugin_name.str,
native_password_plugin_name.length, native_password_plugin_name.length,
@ -3769,15 +3753,17 @@ void set_authentication_plugin_from_password(const User_table& user_table,
} }
else else
{ {
DBUG_ASSERT(password_length == SCRAMBLED_PASSWORD_CHAR_LENGTH_323); DBUG_ASSERT(password.length == SCRAMBLED_PASSWORD_CHAR_LENGTH_323);
user_table.plugin()->store(old_password_plugin_name.str, user_table.plugin()->store(old_password_plugin_name.str,
old_password_plugin_name.length, old_password_plugin_name.length,
system_charset_info); system_charset_info);
} }
user_table.authentication_string()->store(password, user_table.authentication_string()->store(password.str,
password_length, password.length,
system_charset_info); system_charset_info);
} }
/** /**
Update record for user in mysql.user privilege table with new password. Update record for user in mysql.user privilege table with new password.
@ -3786,14 +3772,13 @@ void set_authentication_plugin_from_password(const User_table& user_table,
@param host Hostname @param host Hostname
@param user Username @param user Username
@param new_password New password hash @param new_password New password hash
@param new_password_len Length of new password hash
@see change_password @see change_password
*/ */
static bool update_user_table(THD *thd, const User_table& user_table, static bool update_user_table(THD *thd, const User_table& user_table,
const char *host, const char *user, const char *host, const char *user,
const char *new_password, size_t new_password_len) const LEX_CSTRING &new_password)
{ {
char user_key[MAX_KEY_LENGTH]; char user_key[MAX_KEY_LENGTH];
int error; int error;
@ -3819,13 +3804,13 @@ static bool update_user_table(THD *thd, const User_table& user_table,
if (user_table.plugin()) if (user_table.plugin())
{ {
set_authentication_plugin_from_password(user_table, new_password, set_plugin_from_password(user_table, new_password);
new_password_len); if (user_table.password())
new_password_len= 0; user_table.password()->reset();
} }
else
if (user_table.password()) user_table.password()->store(new_password.str, new_password.len,
user_table.password()->store(new_password, new_password_len, system_charset_info); system_charset_info);
if (unlikely(error= table->file->ha_update_row(table->record[1], if (unlikely(error= table->file->ha_update_row(table->record[1],
@ -3878,7 +3863,7 @@ static bool test_if_create_new_users(THD *thd)
****************************************************************************/ ****************************************************************************/
static int replace_user_table(THD *thd, const User_table &user_table, static int replace_user_table(THD *thd, const User_table &user_table,
LEX_USER &combo, LEX_USER *combo,
ulong rights, bool revoke_grant, ulong rights, bool revoke_grant,
bool can_create_user, bool no_auto_create) bool can_create_user, bool no_auto_create)
{ {
@ -3886,17 +3871,17 @@ static int replace_user_table(THD *thd, const User_table &user_table,
bool old_row_exists=0; bool old_row_exists=0;
char what= (revoke_grant) ? 'N' : 'Y'; char what= (revoke_grant) ? 'N' : 'Y';
uchar user_key[MAX_KEY_LENGTH]; uchar user_key[MAX_KEY_LENGTH];
bool handle_as_role= combo.is_role(); bool handle_as_role= combo->is_role();
LEX *lex= thd->lex; LEX *lex= thd->lex;
TABLE *table= user_table.table(); TABLE *table= user_table.table();
DBUG_ENTER("replace_user_table"); DBUG_ENTER("replace_user_table");
mysql_mutex_assert_owner(&acl_cache->lock); mysql_mutex_assert_owner(&acl_cache->lock);
if (combo.pwhash.str && combo.pwhash.str[0]) if (combo->pwhash.str && combo->pwhash.str[0])
{ {
if (combo.pwhash.length != SCRAMBLED_PASSWORD_CHAR_LENGTH && if (combo->pwhash.length != SCRAMBLED_PASSWORD_CHAR_LENGTH &&
combo.pwhash.length != SCRAMBLED_PASSWORD_CHAR_LENGTH_323) combo->pwhash.length != SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
{ {
DBUG_ASSERT(0); DBUG_ASSERT(0);
my_error(ER_PASSWD_LENGTH, MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH); my_error(ER_PASSWD_LENGTH, MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH);
@ -3904,7 +3889,7 @@ static int replace_user_table(THD *thd, const User_table &user_table,
} }
} }
else else
combo.pwhash= empty_clex_str; combo->pwhash= empty_clex_str;
/* if the user table is not up to date, we can't handle role updates */ /* if the user table is not up to date, we can't handle role updates */
if (!user_table.is_role() && handle_as_role) if (!user_table.is_role() && handle_as_role)
@ -3916,9 +3901,9 @@ static int replace_user_table(THD *thd, const User_table &user_table,
} }
table->use_all_columns(); table->use_all_columns();
user_table.host()->store(combo.host.str,combo.host.length, user_table.host()->store(combo->host.str,combo->host.length,
system_charset_info); system_charset_info);
user_table.user()->store(combo.user.str,combo.user.length, user_table.user()->store(combo->user.str,combo->user.length,
system_charset_info); system_charset_info);
key_copy(user_key, table->record[0], table->key_info, key_copy(user_key, table->record[0], table->key_info,
table->key_info->key_length); table->key_info->key_length);
@ -3930,7 +3915,7 @@ static int replace_user_table(THD *thd, const User_table &user_table,
/* what == 'N' means revoke */ /* what == 'N' means revoke */
if (what == 'N') if (what == 'N')
{ {
my_error(ER_NONEXISTING_GRANT, MYF(0), combo.user.str, combo.host.str); my_error(ER_NONEXISTING_GRANT, MYF(0), combo->user.str, combo->host.str);
goto end; goto end;
} }
/* /*
@ -3946,7 +3931,7 @@ static int replace_user_table(THD *thd, const User_table &user_table,
see also test_if_create_new_users() see also test_if_create_new_users()
*/ */
else if (!combo.pwhash.length && !combo.plugin.length && no_auto_create) else if (!combo->pwhash.length && !combo->plugin.length && no_auto_create)
{ {
my_error(ER_PASSWORD_NO_MATCH, MYF(0)); my_error(ER_PASSWORD_NO_MATCH, MYF(0));
goto end; goto end;
@ -3956,20 +3941,20 @@ static int replace_user_table(THD *thd, const User_table &user_table,
my_error(ER_CANT_CREATE_USER_WITH_GRANT, MYF(0)); my_error(ER_CANT_CREATE_USER_WITH_GRANT, MYF(0));
goto end; goto end;
} }
else if (combo.plugin.str[0]) else if (combo->plugin.str[0])
{ {
if (!plugin_is_ready(&combo.plugin, MYSQL_AUTHENTICATION_PLUGIN)) if (!plugin_is_ready(&combo->plugin, MYSQL_AUTHENTICATION_PLUGIN))
{ {
my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), combo.plugin.str); my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), combo->plugin.str);
goto end; goto end;
} }
} }
old_row_exists = 0; old_row_exists = 0;
restore_record(table,s->default_values); restore_record(table,s->default_values);
user_table.host()->store(combo.host.str,combo.host.length, user_table.host()->store(combo->host.str,combo->host.length,
system_charset_info); system_charset_info);
user_table.user()->store(combo.user.str,combo.user.length, user_table.user()->store(combo->user.str,combo->user.length,
system_charset_info); system_charset_info);
} }
else else
@ -3978,8 +3963,8 @@ static int replace_user_table(THD *thd, const User_table &user_table,
store_record(table,record[1]); // Save copy for update store_record(table,record[1]); // Save copy for update
} }
if (!old_row_exists || combo.pwtext.length || combo.pwhash.length) if (!old_row_exists || combo->pwtext.length || combo->pwhash.length)
if (!handle_as_role && validate_password(&combo, thd)) if (!handle_as_role && validate_password(combo, thd))
goto end; goto end;
/* Update table columns with new privileges */ /* Update table columns with new privileges */
@ -3997,8 +3982,8 @@ static int replace_user_table(THD *thd, const User_table &user_table,
DBUG_PRINT("info",("table fields: %d", user_table.num_fields())); DBUG_PRINT("info",("table fields: %d", user_table.num_fields()));
/* If we don't have a password column, we'll use the authentication_string /* If we don't have a password column, we'll use the authentication_string
column later. */ column later. */
if (combo.pwhash.str[0] && user_table.password()) if (combo->pwhash.str[0] && user_table.password())
user_table.password()->store(combo.pwhash.str, combo.pwhash.length, user_table.password()->store(combo->pwhash.str, combo->pwhash.length,
system_charset_info); system_charset_info);
/* We either have the password column, the plugin column, or both. Otherwise /* We either have the password column, the plugin column, or both. Otherwise
we have a corrupt user table. */ we have a corrupt user table. */
@ -4064,19 +4049,19 @@ static int replace_user_table(THD *thd, const User_table &user_table,
{ {
user_table.plugin()->set_notnull(); user_table.plugin()->set_notnull();
user_table.authentication_string()->set_notnull(); user_table.authentication_string()->set_notnull();
if (combo.plugin.str[0]) if (combo->plugin.str[0])
{ {
DBUG_ASSERT(combo.pwhash.str[0] == 0); DBUG_ASSERT(combo->pwhash.str[0] == 0);
if (user_table.password()) if (user_table.password())
user_table.password()->reset(); user_table.password()->reset();
user_table.plugin()->store(combo.plugin.str, combo.plugin.length, user_table.plugin()->store(combo->plugin.str, combo->plugin.length,
system_charset_info); system_charset_info);
user_table.authentication_string()->store(combo.auth.str, combo.auth.length, user_table.authentication_string()->store(combo->auth.str, combo->auth.length,
system_charset_info); system_charset_info);
} }
if (combo.pwhash.str[0]) if (combo->pwhash.str[0])
{ {
DBUG_ASSERT(combo.plugin.str[0] == 0); DBUG_ASSERT(combo->plugin.str[0] == 0);
/* We have Password column. */ /* We have Password column. */
if (user_table.password()) if (user_table.password())
{ {
@ -4087,9 +4072,7 @@ static int replace_user_table(THD *thd, const User_table &user_table,
{ {
/* We do not have Password column. Use PLUGIN && Authentication_string /* We do not have Password column. Use PLUGIN && Authentication_string
columns instead. */ columns instead. */
set_authentication_plugin_from_password(user_table, set_plugin_from_password(user_table, combo->pwhash);
combo.pwhash.str,
combo.pwhash.length);
} }
} }
@ -4152,34 +4135,20 @@ end:
if (old_row_exists) if (old_row_exists)
{ {
if (handle_as_role) if (handle_as_role)
acl_update_role(combo.user.str, rights); acl_update_role(combo->user.str, rights);
else else
acl_update_user(combo.user.str, combo.host.str, acl_update_user(*combo, lex->ssl_type, lex->ssl_cipher,
combo.pwhash.str, combo.pwhash.length, lex->x509_issuer, lex->x509_subject, &lex->mqh,
lex->ssl_type, rights);
lex->ssl_cipher,
lex->x509_issuer,
lex->x509_subject,
&lex->mqh,
rights,
&combo.plugin,
&combo.auth);
} }
else else
{ {
if (handle_as_role) if (handle_as_role)
acl_insert_role(combo.user.str, rights); acl_insert_role(combo->user.str, rights);
else else
acl_insert_user(combo.user.str, combo.host.str, acl_insert_user(*combo, lex->ssl_type, lex->ssl_cipher,
combo.pwhash.str, combo.pwhash.length, lex->x509_issuer, lex->x509_subject, &lex->mqh,
lex->ssl_type, rights);
lex->ssl_cipher,
lex->x509_issuer,
lex->x509_subject,
&lex->mqh,
rights,
&combo.plugin,
&combo.auth);
} }
} }
DBUG_RETURN(error); DBUG_RETURN(error);
@ -6465,7 +6434,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
} }
/* Create user if needed */ /* Create user if needed */
error= copy_and_check_auth(Str, tmp_Str, thd) || error= copy_and_check_auth(Str, tmp_Str, thd) ||
replace_user_table(thd, tables.user_table(), *Str, replace_user_table(thd, tables.user_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));
@ -6644,7 +6613,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list,
} }
/* Create user if needed */ /* Create user if needed */
if (copy_and_check_auth(Str, tmp_Str, thd) || if (copy_and_check_auth(Str, tmp_Str, thd) ||
replace_user_table(thd, tables.user_table(), *Str, replace_user_table(thd, tables.user_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)))
@ -6920,7 +6889,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
user_combo.user = username; user_combo.user = username;
if (copy_and_check_auth(&user_combo, &user_combo, thd) || if (copy_and_check_auth(&user_combo, &user_combo, thd) ||
replace_user_table(thd, tables.user_table(), user_combo, 0, replace_user_table(thd, tables.user_table(), &user_combo, 0,
false, create_new_user, false, create_new_user,
no_auto_create_user)) no_auto_create_user))
{ {
@ -7090,7 +7059,7 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
} }
if (copy_and_check_auth(Str, tmp_Str, thd) || if (copy_and_check_auth(Str, tmp_Str, thd) ||
replace_user_table(thd, tables.user_table(), *Str, replace_user_table(thd, tables.user_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)))
@ -10223,7 +10192,7 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role)
} }
} }
if (replace_user_table(thd, tables.user_table(), *user_name, 0, 0, 1, 0)) if (replace_user_table(thd, tables.user_table(), user_name, 0, 0, 1, 0))
{ {
append_user(thd, &wrong_users, user_name); append_user(thd, &wrong_users, user_name);
result= TRUE; result= TRUE;
@ -10514,7 +10483,7 @@ int mysql_alter_user(THD* thd, List<LEX_USER> &users_list)
LEX_USER* lex_user= get_current_user(thd, tmp_lex_user, false); LEX_USER* lex_user= get_current_user(thd, tmp_lex_user, false);
if (!lex_user || if (!lex_user ||
fix_lex_user(thd, lex_user) || fix_lex_user(thd, lex_user) ||
replace_user_table(thd, tables.user_table(), *lex_user, 0, replace_user_table(thd, tables.user_table(), lex_user, 0,
false, false, true)) false, false, true))
{ {
thd->clear_error(); thd->clear_error();
@ -10639,7 +10608,7 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
continue; continue;
} }
if (replace_user_table(thd, tables.user_table(), *lex_user, if (replace_user_table(thd, tables.user_table(), lex_user,
~(ulong)0, 1, 0, 0)) ~(ulong)0, 1, 0, 0))
{ {
result= -1; result= -1;