1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

MDEV-24207: recognise mysql forms of invalid password for mysql_native_password

The main goal of this patch is to prevent MariaDB's native_password_plugin
from "parsing" the hex (or non hex) authentication_string. Due to how the
current code is written, we convert any string (within native_password_get_salt)
that has the appropriate length to a "binary" representation, that can
potentially match a real password.

More specifically,
"*THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE" produces the same results as
"*d13c3c78dafa52d9bce09bdd1adcb7befced1ebe".

The length indicator is the main indicator of an invalid password. We use
use same trick with "invalid" to change its internal representation.

The "parsing" mentioned is by get_salt_from_password down to char_val()
and because if where it is, its effectively a static plugin API that cannot
change.

In supporting these, we support the SHOW CREATE USER from MySQL may have the
hashed password string: *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE.

Obviously this isn't a hash because it contains non-hex characters.

After this patch we do however recognise the pattern;

 [any char, notionally *]{40 chars not all are hex}

as a pattern for an invalid password. This was determined to be the general
pattern that MySQL used.

Reviewers: Sergei G, Vicentiu
This commit is contained in:
Daniel Black
2020-10-24 21:01:07 +11:00
parent 0ea650022d
commit d4c35fb21b
3 changed files with 29 additions and 4 deletions

View File

@ -14203,6 +14203,7 @@ static int native_password_get_salt(const char *hash, size_t hash_length,
{
DBUG_ASSERT(sizeof(invalid_password) > SCRAMBLE_LENGTH);
DBUG_ASSERT(*out_length >= SCRAMBLE_LENGTH);
DBUG_ASSERT(*out_length >= sizeof(invalid_password));
if (hash_length == 0)
{
*out_length= 0;
@ -14213,14 +14214,27 @@ static int native_password_get_salt(const char *hash, size_t hash_length,
{
if (hash_length == 7 && strcmp(hash, "invalid") == 0)
{
memcpy(out, invalid_password, SCRAMBLED_PASSWORD_CHAR_LENGTH);
*out_length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
memcpy(out, invalid_password, sizeof(invalid_password));
*out_length= sizeof(invalid_password);
return 0;
}
my_error(ER_PASSWD_LENGTH, MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH);
return 1;
}
for (const char *c= hash + 1; c < (hash + hash_length); c++)
{
/* If any non-hex characters are found, mark the password as invalid. */
if (!(*c >= '0' && *c <= '9') &&
!(*c >= 'A' && *c <= 'F') &&
!(*c >= 'a' && *c <= 'f'))
{
memcpy(out, invalid_password, sizeof(invalid_password));
*out_length= sizeof(invalid_password);
return 0;
}
}
*out_length= SCRAMBLE_LENGTH;
get_salt_from_password(out, hash);
return 0;