Bug #17357528 BACKPORT BUG#16513435 TO 5.5 AND 5.6
Description: Backporting BUG#16513435 to 5.5 and 5.6 This is a fix for REMOTE PREAUTH USER ENUMERATION FLAW bug
This commit is contained in:
parent
1edfef74a8
commit
3bba29a397
@ -6,6 +6,6 @@ exec MYSQL PLUGIN_AUTH_OPT --default_auth=qa_auth_client -h localhost -P MASTER_
|
|||||||
current_user() user() @@local.proxy_user @@local.external_user
|
current_user() user() @@local.proxy_user @@local.external_user
|
||||||
qa_test_11_dest@% qa_test_11_user@localhost 'qa_test_11_user'@'%' 'qa_test_11_user'@'%'
|
qa_test_11_dest@% qa_test_11_user@localhost 'qa_test_11_user'@'%' 'qa_test_11_user'@'%'
|
||||||
exec MYSQL PLUGIN_AUTH_OPT --default_auth=qa_auth_client -h localhost -P MASTER_MYPORT -u qa_test_2_user --password=qa_test_11_dest test_user_db -e "SELECT current_user(),user(),@@local.proxy_user,@@local.external_user;" 2>&1
|
exec MYSQL PLUGIN_AUTH_OPT --default_auth=qa_auth_client -h localhost -P MASTER_MYPORT -u qa_test_2_user --password=qa_test_11_dest test_user_db -e "SELECT current_user(),user(),@@local.proxy_user,@@local.external_user;" 2>&1
|
||||||
ERROR 1045 (28000): Access denied for user 'qa_test_2_user'@'localhost' (using password: NO)
|
ERROR 1045 (28000): Access denied for user 'qa_test_2_user'@'localhost' (using password: YES)
|
||||||
DROP USER qa_test_11_user, qa_test_11_dest;
|
DROP USER qa_test_11_user, qa_test_11_dest;
|
||||||
DROP DATABASE test_user_db;
|
DROP DATABASE test_user_db;
|
||||||
|
@ -222,6 +222,7 @@ public:
|
|||||||
const char *ssl_cipher, *x509_issuer, *x509_subject;
|
const char *ssl_cipher, *x509_issuer, *x509_subject;
|
||||||
LEX_STRING plugin;
|
LEX_STRING plugin;
|
||||||
LEX_STRING auth_string;
|
LEX_STRING auth_string;
|
||||||
|
bool can_authenticate;
|
||||||
|
|
||||||
ACL_USER *copy(MEM_ROOT *root)
|
ACL_USER *copy(MEM_ROOT *root)
|
||||||
{
|
{
|
||||||
@ -811,6 +812,16 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
|
|||||||
{
|
{
|
||||||
ACL_USER user;
|
ACL_USER user;
|
||||||
bzero(&user, sizeof(user));
|
bzero(&user, sizeof(user));
|
||||||
|
|
||||||
|
/*
|
||||||
|
All accounts can authenticate per default. This will change when
|
||||||
|
we add a new field to the user table.
|
||||||
|
|
||||||
|
Currently this flag is only set to false when authentication is attempted
|
||||||
|
using an unknown user name.
|
||||||
|
*/
|
||||||
|
user.can_authenticate= true;
|
||||||
|
|
||||||
update_hostname(&user.host, get_field(&mem, table->field[0]));
|
update_hostname(&user.host, get_field(&mem, table->field[0]));
|
||||||
user.user= get_field(&mem, table->field[1]);
|
user.user= get_field(&mem, table->field[1]);
|
||||||
if (check_no_resolve && hostname_requires_resolving(user.host.hostname))
|
if (check_no_resolve && hostname_requires_resolving(user.host.hostname))
|
||||||
@ -1465,6 +1476,14 @@ static void acl_insert_user(const char *user, const char *host,
|
|||||||
ACL_USER acl_user;
|
ACL_USER acl_user;
|
||||||
|
|
||||||
mysql_mutex_assert_owner(&acl_cache->lock);
|
mysql_mutex_assert_owner(&acl_cache->lock);
|
||||||
|
/*
|
||||||
|
All accounts can authenticate per default. This will change when
|
||||||
|
we add a new field to the user table.
|
||||||
|
|
||||||
|
Currently this flag is only set to false when authentication is attempted
|
||||||
|
using an unknown user name.
|
||||||
|
*/
|
||||||
|
acl_user.can_authenticate= true;
|
||||||
|
|
||||||
acl_user.user=*user ? strdup_root(&mem,user) : 0;
|
acl_user.user=*user ? strdup_root(&mem,user) : 0;
|
||||||
update_hostname(&acl_user.host, *host ? strdup_root(&mem, host): 0);
|
update_hostname(&acl_user.host, *host ? strdup_root(&mem, host): 0);
|
||||||
@ -8000,6 +8019,10 @@ struct MPVIO_EXT :public MYSQL_PLUGIN_VIO
|
|||||||
char *host;
|
char *host;
|
||||||
Thd_charset_adapter *charset_adapter;
|
Thd_charset_adapter *charset_adapter;
|
||||||
LEX_STRING acl_user_plugin;
|
LEX_STRING acl_user_plugin;
|
||||||
|
bool can_authenticate()
|
||||||
|
{
|
||||||
|
return (acl_user && acl_user->can_authenticate);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -8301,6 +8324,34 @@ static bool send_plugin_request_packet(MPVIO_EXT *mpvio,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
|
|
||||||
|
/**
|
||||||
|
When authentication is attempted using an unknown username a dummy user
|
||||||
|
account with no authentication capabilites is assigned to the connection.
|
||||||
|
This is done increase the cost of enumerating user accounts based on
|
||||||
|
authentication protocol.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ACL_USER *decoy_user(const LEX_STRING &username,
|
||||||
|
MEM_ROOT *mem)
|
||||||
|
{
|
||||||
|
ACL_USER *user= (ACL_USER *) alloc_root(mem, sizeof(ACL_USER));
|
||||||
|
user->can_authenticate= false;
|
||||||
|
user->user= strmake_root(mem, username.str, username.length);
|
||||||
|
user->auth_string= empty_lex_str;
|
||||||
|
user->ssl_cipher= empty_c_string;
|
||||||
|
user->x509_issuer= empty_c_string;
|
||||||
|
user->x509_subject= empty_c_string;
|
||||||
|
user->salt_len= 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
For now the common default account is used. Improvements might involve
|
||||||
|
mapping a consistent hash of a username to a range of plugins.
|
||||||
|
*/
|
||||||
|
user->plugin= *default_auth_plugin_name;
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Finds acl entry in user database for authentication purposes.
|
Finds acl entry in user database for authentication purposes.
|
||||||
|
|
||||||
@ -8342,8 +8393,14 @@ static bool find_mpvio_user(MPVIO_EXT *mpvio)
|
|||||||
|
|
||||||
if (!mpvio->acl_user)
|
if (!mpvio->acl_user)
|
||||||
{
|
{
|
||||||
login_failed_error(mpvio, mpvio->auth_info.password_used);
|
/*
|
||||||
DBUG_RETURN (1);
|
Pretend the user exists; let the plugin decide how to handle
|
||||||
|
bad credentials.
|
||||||
|
*/
|
||||||
|
LEX_STRING usr= { mpvio->auth_info.user_name,
|
||||||
|
mpvio->auth_info.user_name_length };
|
||||||
|
mpvio->acl_user= decoy_user(usr, mpvio->mem_root);
|
||||||
|
mpvio->acl_user_plugin= mpvio->acl_user->plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* user account requires non-default plugin and the client is too old */
|
/* user account requires non-default plugin and the client is too old */
|
||||||
@ -8465,7 +8522,9 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length)
|
|||||||
|
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
if (find_mpvio_user(mpvio))
|
if (find_mpvio_user(mpvio))
|
||||||
|
{
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
|
||||||
char *client_plugin;
|
char *client_plugin;
|
||||||
if (mpvio->client_capabilities & CLIENT_PLUGIN_AUTH)
|
if (mpvio->client_capabilities & CLIENT_PLUGIN_AUTH)
|
||||||
@ -9450,6 +9509,8 @@ acl_authenticate(THD *thd, uint connect_errors, uint com_change_user_pkt_len)
|
|||||||
|
|
||||||
if (parse_com_change_user_packet(&mpvio, com_change_user_pkt_len))
|
if (parse_com_change_user_packet(&mpvio, com_change_user_pkt_len))
|
||||||
{
|
{
|
||||||
|
if (!thd->is_error())
|
||||||
|
login_failed_error(&mpvio, mpvio.auth_info.password_used);
|
||||||
server_mpvio_update_thd(thd, &mpvio);
|
server_mpvio_update_thd(thd, &mpvio);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
@ -9515,6 +9576,11 @@ acl_authenticate(THD *thd, uint connect_errors, uint com_change_user_pkt_len)
|
|||||||
mpvio.db.str ? mpvio.db.str : (char*) "");
|
mpvio.db.str ? mpvio.db.str : (char*) "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res == CR_OK && !mpvio.can_authenticate())
|
||||||
|
{
|
||||||
|
res= CR_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (res > CR_OK && mpvio.status != MPVIO_EXT::SUCCESS)
|
if (res > CR_OK && mpvio.status != MPVIO_EXT::SUCCESS)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(mpvio.status == MPVIO_EXT::FAILURE);
|
DBUG_ASSERT(mpvio.status == MPVIO_EXT::FAILURE);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user