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
|
||||
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
|
||||
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 DATABASE test_user_db;
|
||||
|
@ -222,6 +222,7 @@ public:
|
||||
const char *ssl_cipher, *x509_issuer, *x509_subject;
|
||||
LEX_STRING plugin;
|
||||
LEX_STRING auth_string;
|
||||
bool can_authenticate;
|
||||
|
||||
ACL_USER *copy(MEM_ROOT *root)
|
||||
{
|
||||
@ -811,6 +812,16 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
|
||||
{
|
||||
ACL_USER 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]));
|
||||
user.user= get_field(&mem, table->field[1]);
|
||||
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;
|
||||
|
||||
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;
|
||||
update_hostname(&acl_user.host, *host ? strdup_root(&mem, host): 0);
|
||||
@ -8000,6 +8019,10 @@ struct MPVIO_EXT :public MYSQL_PLUGIN_VIO
|
||||
char *host;
|
||||
Thd_charset_adapter *charset_adapter;
|
||||
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
|
||||
|
||||
/**
|
||||
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.
|
||||
|
||||
@ -8342,8 +8393,14 @@ static bool find_mpvio_user(MPVIO_EXT *mpvio)
|
||||
|
||||
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 */
|
||||
@ -8465,7 +8522,9 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length)
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (find_mpvio_user(mpvio))
|
||||
{
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
char *client_plugin;
|
||||
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 (!thd->is_error())
|
||||
login_failed_error(&mpvio, mpvio.auth_info.password_used);
|
||||
server_mpvio_update_thd(thd, &mpvio);
|
||||
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*) "");
|
||||
}
|
||||
|
||||
if (res == CR_OK && !mpvio.can_authenticate())
|
||||
{
|
||||
res= CR_ERROR;
|
||||
}
|
||||
|
||||
if (res > CR_OK && mpvio.status != MPVIO_EXT::SUCCESS)
|
||||
{
|
||||
DBUG_ASSERT(mpvio.status == MPVIO_EXT::FAILURE);
|
||||
|
Loading…
x
Reference in New Issue
Block a user