Commit 9e23d9cf authored by Nikita Malyavin's avatar Nikita Malyavin

MDEV-34854 Parsec sends garbage when using an empty password

When an empty password is set, the server doesn't call
st_mysql_auth::hash_password and leaves
MYSQL_SERVER_AUTH_INFO::auth_string empty.

Normally, auth_string would be a string of readable characters beginnging from
"P", followed by a single digit, like "P0". In this case, auth_string[0] will
be '\0', followed by a garbage.

In case of empty auth_string, let's generate an empty password ad-hoc. It makes
no sense save it to auth_string, since it's a sopy of a globally stored object.
This means also, that ext-salt will be random per each login.
parent a5b80531
......@@ -28,3 +28,18 @@ test.have_ssl()
yes
drop function have_ssl;
drop user test1@'%';
# MDEV-34854 Parsec sends garbage when using an empty password
create user test2@'%' identified via parsec using PASSWORD('');
show grants for test2@'%';
Grants for test2@%
GRANT USAGE ON *.* TO `test2`@`%` IDENTIFIED VIA parsec
connect con4, localhost, test2,;
select 4, USER(), CURRENT_USER();
4 USER() CURRENT_USER()
4 test2@localhost test2@%
disconnect con4;
connect(localhost,test2,wrong_pwd,test,MASTER_MYPORT,MASTER_MYSOCK);
connect con5, localhost, test2, "wrong_pwd";
ERROR 28000: Access denied for user 'test2'@'localhost' (using password: NO)
connection default;
drop user test2@'%';
......@@ -43,3 +43,17 @@ if ($MTR_COMBINATION_WIN) {
drop function have_ssl;
drop user test1@'%';
--echo # MDEV-34854 Parsec sends garbage when using an empty password
create user test2@'%' identified via parsec using PASSWORD('');
show grants for test2@'%';
connect con4, localhost, test2,;
select 4, USER(), CURRENT_USER();
disconnect con4;
--replace_result $MASTER_MYSOCK MASTER_MYSOCK $MASTER_MYPORT MASTER_MYPORT
--error ER_ACCESS_DENIED_ERROR
connect con5, localhost, test2, "wrong_pwd";
connection default;
drop user test2@'%';
......@@ -166,6 +166,24 @@ int ed25519_derive_public_key(const uchar *raw_private_key, uchar *pub_key)
#endif
}
static int hash_password(const char *password, size_t password_length,
Passwd_in_memory *derivation)
{
derivation->algorithm= 'P';
derivation->iterations= 0;
int err= my_random_bytes(derivation->salt, sizeof(derivation->salt));
if (err != MY_AES_OK)
return 1;
uchar derived_key[PBKDF2_HASH_LENGTH];
if (compute_derived_key(password, password_length, derivation, derived_key))
return 1;
if (ed25519_derive_public_key(derived_key, derivation->pub_key))
return 1;
return 0;
}
static
int hash_password(const char *password, size_t password_length,
char *hash, size_t *hash_length)
......@@ -175,15 +193,7 @@ int hash_password(const char *password, size_t password_length,
return 1;
Passwd_in_memory memory;
memory.algorithm= 'P';
memory.iterations= 0;
my_random_bytes(memory.salt, sizeof(memory.salt));
uchar derived_key[PBKDF2_HASH_LENGTH];
if (compute_derived_key(password, password_length, &memory, derived_key))
return 1;
if (ed25519_derive_public_key(derived_key, memory.pub_key))
if (hash_password(password, password_length, &memory))
return 1;
stored->algorithm= memory.algorithm;
......@@ -260,7 +270,14 @@ int auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
auto passwd= (Passwd_in_memory*)info->auth_string;
if (vio->write_packet(vio, (uchar*)info->auth_string, 2 + CHALLENGE_SALT_LENGTH))
Passwd_in_memory zero_passwd_derivation;
if (info->auth_string_length == 0) // Empty passwd
{
hash_password("", 0, &zero_passwd_derivation);
passwd= &zero_passwd_derivation;
}
if (vio->write_packet(vio, (uchar*)passwd, 2 + CHALLENGE_SALT_LENGTH))
return CR_ERROR;
Client_signed_response *client_response;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment