summaryrefslogtreecommitdiff
path: root/sql/sql_acl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_acl.cc')
-rw-r--r--sql/sql_acl.cc162
1 files changed, 103 insertions, 59 deletions
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 4b90209a472..9cc9efae6f8 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -863,32 +863,30 @@ static char *fix_plugin_ptr(char *name)
}
/**
- Fix ACL::plugin pointer to point to a hard-coded string, if appropriate
+ Fix a LEX_STRING *plugin pointer to point to a hard-coded string,
+ if appropriate
Make sure that if ACL_USER's plugin is a built-in, then it points
to a hard coded string, not to an allocated copy. Run-time, for
authentication, we want to be able to detect built-ins by comparing
pointers, not strings.
- Additionally - update the salt if the plugin is built-in.
-
@retval 0 the pointers were fixed
@retval 1 this ACL_USER uses a not built-in plugin
*/
-static bool fix_user_plugin_ptr(ACL_USER *user)
+static bool fix_user_plugin_ptr(LEX_STRING *plugin_ptr)
{
- if (my_strcasecmp(system_charset_info, user->plugin.str,
+ DBUG_ASSERT(plugin_ptr);
+ if (my_strcasecmp(system_charset_info, plugin_ptr->str,
native_password_plugin_name.str) == 0)
- user->plugin= native_password_plugin_name;
+ *plugin_ptr= native_password_plugin_name;
else
- if (my_strcasecmp(system_charset_info, user->plugin.str,
+ if (my_strcasecmp(system_charset_info, plugin_ptr->str,
old_password_plugin_name.str) == 0)
- user->plugin= old_password_plugin_name;
+ *plugin_ptr= old_password_plugin_name;
else
return true;
- if (user->auth_string.length)
- set_user_salt(user, user->auth_string.str, user->auth_string.length);
return false;
}
@@ -967,6 +965,23 @@ my_bool acl_init(bool dont_read_acl_tables)
}
/**
+ Check if the password length provided matches supported native formats.
+*/
+static bool password_length_valid(int password_length)
+{
+ switch (password_length)
+ {
+ case 0: /* no password */
+ case SCRAMBLED_PASSWORD_CHAR_LENGTH:
+ return TRUE;
+ case SCRAMBLED_PASSWORD_CHAR_LENGTH_323:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+/**
Choose from either native or old password plugins when assigning a password
*/
@@ -1257,22 +1272,43 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
char *tmpstr= get_field(&acl_memroot, table->field[next_field++]);
if (tmpstr)
{
+ LEX_STRING auth;
+ auth.str = safe_str(get_field(&acl_memroot, table->field[next_field++]));
+ auth.length = strlen(auth.str);
user.plugin.str= tmpstr;
user.plugin.length= strlen(user.plugin.str);
- user.auth_string.str=
- safe_str(get_field(&acl_memroot, table->field[next_field++]));
- user.auth_string.length= strlen(user.auth_string.str);
-
- if (user.auth_string.length && password_len)
+ if (fix_user_plugin_ptr(&user.plugin)) // Non native plugin.
{
- sql_print_warning("'user' entry '%s@%s' has both a password "
- "and an authentication plugin specified. The "
- "password will be ignored.",
- safe_str(user.user.str),
- safe_str(user.host.hostname));
+ user.auth_string= auth;
+ if (password_len)
+ {
+ sql_print_warning("'user' entry '%s@%s' has both a password "
+ "and an authentication plugin specified. The "
+ "password will be ignored.",
+ safe_str(user.user.str),
+ safe_str(user.host.hostname));
+ }
+ }
+ else // Native plugin.
+ {
+ /*
+ Password field, if not empty, has precedence over
+ authentication_string field, only for native plugins.
+ See MDEV-6253 and MDEV-7985 for reasoning.
+ */
+ if (!password_len)
+ {
+ user.auth_string = auth;
+ if (!password_length_valid(auth.length))
+ {
+ sql_print_warning("Found invalid password for user: '%s@%s';"
+ " Ignoring user", safe_str(user.user.str),
+ safe_str(user.host.hostname));
+ continue;
+ }
+ set_user_salt(&user, auth.str, auth.length);
+ }
}
-
- fix_user_plugin_ptr(&user);
}
}
}
@@ -1971,8 +2007,13 @@ static void acl_update_user(const char *user, const char *host,
acl_user->auth_string.str= auth->str ?
strmake_root(&acl_memroot, auth->str, auth->length) : const_cast<char*>("");
acl_user->auth_string.length= auth->length;
- if (fix_user_plugin_ptr(acl_user))
+ if (acl_user->plugin.str != native_password_plugin_name.str &&
+ acl_user->plugin.str != old_password_plugin_name.str)
acl_user->plugin.str= strmake_root(&acl_memroot, plugin->str, plugin->length);
+ else
+ set_user_salt(acl_user, acl_user->auth_string.str,
+ acl_user->auth_string.length);
+
}
else
if (password[0])
@@ -2047,8 +2088,12 @@ static void acl_insert_user(const char *user, const char *host,
acl_user.auth_string.str= auth->str ?
strmake_root(&acl_memroot, auth->str, auth->length) : const_cast<char*>("");
acl_user.auth_string.length= auth->length;
- if (fix_user_plugin_ptr(&acl_user))
+ if (acl_user.plugin.str != native_password_plugin_name.str &&
+ acl_user.plugin.str != old_password_plugin_name.str)
acl_user.plugin.str= strmake_root(&acl_memroot, plugin->str, plugin->length);
+ else
+ set_user_salt(&acl_user, acl_user.auth_string.str,
+ acl_user.auth_string.length);
}
else
{
@@ -3014,17 +3059,20 @@ static int replace_user_table(THD *thd, TABLE *table, LEX_USER &combo,
mysql_mutex_assert_owner(&acl_cache->lock);
+ size_t length_to_check = 0;
+ combo.password = combo.password.str ? combo.password : empty_lex_str;
if (combo.password.str && combo.password.str[0])
+ length_to_check = combo.password.length;
+ else if (!fix_user_plugin_ptr(&combo.plugin))
+ {
+ length_to_check = combo.auth.length;
+ }
+
+ if (!password_length_valid(length_to_check))
{
- if (combo.password.length != SCRAMBLED_PASSWORD_CHAR_LENGTH &&
- combo.password.length != SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
- {
my_error(ER_PASSWD_LENGTH, MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH);
DBUG_RETURN(-1);
- }
}
- else
- combo.password= empty_lex_str;
/* if the user table is not up to date, we can't handle role updates */
if (table->s->fields <= ROLE_ASSIGN_COLUMN_IDX && handle_as_role)
@@ -8802,10 +8850,30 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
if (struct_no == ROLES_MAPPINGS_HASH)
{
const char* role= role_grant_pair->r_uname? role_grant_pair->r_uname: "";
- if (user_from->is_role() ? strcmp(user_from->user.str, role) :
- (strcmp(user_from->user.str, user) ||
- my_strcasecmp(system_charset_info, user_from->host.str, host)))
- continue;
+ if (user_from->is_role())
+ {
+ /* When searching for roles within the ROLES_MAPPINGS_HASH, we have
+ to check both the user field as well as the role field for a match.
+
+ It is possible to have a role granted to a role. If we are going
+ to modify the mapping entry, it needs to be done on either on the
+ "user" end (here represented by a role) or the "role" end. At least
+ one part must match.
+
+ If the "user" end has a not-empty host string, it can never match
+ as we are searching for a role here. A role always has an empty host
+ string.
+ */
+ if ((*host || strcmp(user_from->user.str, user)) &&
+ strcmp(user_from->user.str, role))
+ continue;
+ }
+ else
+ {
+ if (strcmp(user_from->user.str, user) ||
+ my_strcasecmp(system_charset_info, user_from->host.str, host))
+ continue;
+ }
}
else
{
@@ -9840,7 +9908,6 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
List<LEX_USER> user_list;
bool result;
ACL_USER *au;
- char passwd_buff[SCRAMBLED_PASSWORD_CHAR_LENGTH+1];
Dummy_error_handler error_handler;
DBUG_ENTER("sp_grant_privileges");
@@ -9881,33 +9948,10 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
if(au)
{
- if (au->salt_len)
- {
- if (au->salt_len == SCRAMBLE_LENGTH)
- {
- make_password_from_salt(passwd_buff, au->salt);
- combo->password.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;
- }
- 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;
- }
-
if (au->plugin.str != native_password_plugin_name.str &&
au->plugin.str != old_password_plugin_name.str)
- {
combo->plugin= au->plugin;
- combo->auth= au->auth_string;
- }
+ combo->auth= au->auth_string;
}
if (user_list.push_back(combo))