Commit ad17a89e authored by Nikita Malyavin's avatar Nikita Malyavin

MDEV-12320 configurable default authentication plugin for the server

A default auth plugin acts as a first one responding to the client. Its
responsibility is also to generate the scramble, that'll be used for
generating ssl zero-config, both by client and server.

For PARSEC, we will use first 20 bytes of the scramble that is sent by the
first message from the server.
parent 048dbc0d
...@@ -111,6 +111,11 @@ typedef struct st_mysql_server_auth_info ...@@ -111,6 +111,11 @@ typedef struct st_mysql_server_auth_info
*/ */
MYSQL_THD thd; MYSQL_THD thd;
/**
Pointer to thd->scramble, which is used to verify the session handshake.
*/
char *scramble;
} MYSQL_SERVER_AUTH_INFO; } MYSQL_SERVER_AUTH_INFO;
/** /**
......
...@@ -704,6 +704,7 @@ typedef struct st_mysql_server_auth_info ...@@ -704,6 +704,7 @@ typedef struct st_mysql_server_auth_info
const char *host_or_ip; const char *host_or_ip;
unsigned int host_or_ip_length; unsigned int host_or_ip_length;
THD* thd; THD* thd;
char *scramble;
} MYSQL_SERVER_AUTH_INFO; } MYSQL_SERVER_AUTH_INFO;
struct st_mysql_auth struct st_mysql_auth
{ {
......
Subproject commit de6305915f86bb33c83b1fe782a2b8a76920aec1 Subproject commit d67a1a40860c2afc172556fe7fc8e0fa48213bf4
...@@ -227,6 +227,9 @@ The following specify which files/extra groups are read (specified before remain ...@@ -227,6 +227,9 @@ The following specify which files/extra groups are read (specified before remain
--deadlock-timeout-short=# --deadlock-timeout-short=#
Short timeout for the two-step deadlock detection (in Short timeout for the two-step deadlock detection (in
microseconds) microseconds)
--default-auth-plugin[=name]
Default plugin, that will be tried first when
authenticating new connections
--default-password-lifetime=# --default-password-lifetime=#
This defines the global password expiration policy. 0 This defines the global password expiration policy. 0
means automatic password expiration is disabled. If the means automatic password expiration is disabled. If the
...@@ -1649,6 +1652,7 @@ deadlock-search-depth-long 15 ...@@ -1649,6 +1652,7 @@ deadlock-search-depth-long 15
deadlock-search-depth-short 4 deadlock-search-depth-short 4
deadlock-timeout-long 50000000 deadlock-timeout-long 50000000
deadlock-timeout-short 10000 deadlock-timeout-short 10000
default-auth-plugin mysql_native_password
default-password-lifetime 0 default-password-lifetime 0
default-regex-flags default-regex-flags
default-storage-engine myisam default-storage-engine myisam
......
...@@ -18,6 +18,10 @@ connect(localhost,test1,wrong_pwd,test,MASTER_MYPORT,MASTER_MYSOCK); ...@@ -18,6 +18,10 @@ connect(localhost,test1,wrong_pwd,test,MASTER_MYPORT,MASTER_MYSOCK);
connect con3, localhost, test1, wrong_pwd; connect con3, localhost, test1, wrong_pwd;
ERROR 28000: Access denied for user 'test1'@'localhost' (using password: NO) ERROR 28000: Access denied for user 'test1'@'localhost' (using password: NO)
connection default; connection default;
select "change_user success" as "result";
result
change_user success
ERROR 28000: Access denied for user 'test1'@'localhost' (using password: NO)
create function have_ssl() returns char(3) create function have_ssl() returns char(3)
return (select if(variable_value > '','yes','no') as 'have_ssl' return (select if(variable_value > '','yes','no') as 'have_ssl'
from information_schema.session_status from information_schema.session_status
......
[normal]
[default]
--default-auth-plugin=parsec
...@@ -26,6 +26,14 @@ connect con3, localhost, test1, wrong_pwd; ...@@ -26,6 +26,14 @@ connect con3, localhost, test1, wrong_pwd;
connection default; connection default;
change_user test1,pwd,;
select "change_user success" as "result";
change_user root,,test;
--replace_result $MASTER_MYSOCK MASTER_MYSOCK $MASTER_MYPORT MASTER_MYPORT
--error ER_ACCESS_DENIED_ERROR
change_user test1,bad_pwd,test;
create function have_ssl() returns char(3) create function have_ssl() returns char(3)
return (select if(variable_value > '','yes','no') as 'have_ssl' return (select if(variable_value > '','yes','no') as 'have_ssl'
from information_schema.session_status from information_schema.session_status
......
...@@ -842,6 +842,16 @@ NUMERIC_BLOCK_SIZE 1 ...@@ -842,6 +842,16 @@ NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL ENUM_VALUE_LIST NULL
READ_ONLY NO READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME DEFAULT_AUTH_PLUGIN
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE VARCHAR
VARIABLE_COMMENT Default plugin, that will be tried first when authenticating new connections
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST NULL
READ_ONLY YES
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME DEFAULT_MASTER_CONNECTION VARIABLE_NAME DEFAULT_MASTER_CONNECTION
VARIABLE_SCOPE SESSION ONLY VARIABLE_SCOPE SESSION ONLY
VARIABLE_TYPE VARCHAR VARIABLE_TYPE VARCHAR
......
...@@ -248,6 +248,8 @@ int auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) ...@@ -248,6 +248,8 @@ int auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
} scramble_pair; } scramble_pair;
my_random_bytes(scramble_pair.server, CHALLENGE_SCRAMBLE_LENGTH); my_random_bytes(scramble_pair.server, CHALLENGE_SCRAMBLE_LENGTH);
memcpy(info->scramble, scramble_pair.server, SCRAMBLE_LENGTH);
info->scramble[SCRAMBLE_LENGTH]= 0;
if (vio->write_packet(vio, scramble_pair.server, sizeof(scramble_pair.server))) if (vio->write_packet(vio, scramble_pair.server, sizeof(scramble_pair.server)))
return CR_ERROR; return CR_ERROR;
......
...@@ -80,7 +80,7 @@ const char *safe_vio_type_name(Vio *vio) ...@@ -80,7 +80,7 @@ const char *safe_vio_type_name(Vio *vio)
#include "sql_acl_getsort.ic" #include "sql_acl_getsort.ic"
static Lex_ident_plugin native_password_plugin_name= Lex_ident_plugin native_password_plugin_name=
"mysql_native_password"_Lex_ident_plugin; "mysql_native_password"_Lex_ident_plugin;
...@@ -88,9 +88,8 @@ static Lex_ident_plugin old_password_plugin_name= ...@@ -88,9 +88,8 @@ static Lex_ident_plugin old_password_plugin_name=
"mysql_old_password"_Lex_ident_plugin; "mysql_old_password"_Lex_ident_plugin;
/// @todo make it configurable plugin_ref default_auth_plugin;
LEX_CSTRING *default_auth_plugin_name= &native_password_plugin_name; const char *default_auth_plugin_name= native_password_plugin_name.str;
/* /*
Wildcard host, matches any hostname Wildcard host, matches any hostname
*/ */
...@@ -2543,7 +2542,11 @@ bool acl_init(bool dont_read_acl_tables) ...@@ -2543,7 +2542,11 @@ bool acl_init(bool dont_read_acl_tables)
old_password_plugin= my_plugin_lock_by_name(0, old_password_plugin= my_plugin_lock_by_name(0,
&old_password_plugin_name, MYSQL_AUTHENTICATION_PLUGIN); &old_password_plugin_name, MYSQL_AUTHENTICATION_PLUGIN);
if (!native_password_plugin || !old_password_plugin) Lex_cstring_strlen def_plugin_name(default_auth_plugin_name);
default_auth_plugin= my_plugin_lock_by_name(NULL, &def_plugin_name,
MYSQL_AUTHENTICATION_PLUGIN);
if (!native_password_plugin || !old_password_plugin || !default_auth_plugin)
DBUG_RETURN(1); DBUG_RETURN(1);
if (dont_read_acl_tables) if (dont_read_acl_tables)
...@@ -2945,6 +2948,7 @@ void acl_free(bool end) ...@@ -2945,6 +2948,7 @@ void acl_free(bool end)
acl_cache->clear(1); /* purecov: inspected */ acl_cache->clear(1); /* purecov: inspected */
else else
{ {
plugin_unlock(0, default_auth_plugin);
plugin_unlock(0, native_password_plugin); plugin_unlock(0, native_password_plugin);
plugin_unlock(0, old_password_plugin); plugin_unlock(0, old_password_plugin);
delete acl_cache; delete acl_cache;
...@@ -14386,6 +14390,17 @@ static int server_mpvio_write_packet(MYSQL_PLUGIN_VIO *param, ...@@ -14386,6 +14390,17 @@ static int server_mpvio_write_packet(MYSQL_PLUGIN_VIO *param,
DBUG_RETURN(res); DBUG_RETURN(res);
} }
void mpvio_init_auth_info(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *ai)
{
MPVIO_EXT * const mpvio= (MPVIO_EXT *) vio;
ai->user_name= ai->thd->security_ctx->user;
ai->user_name_length= (uint) strlen(ai->user_name);
ai->auth_string= mpvio->acl_user->auth[mpvio->curr_auth].salt.str;
ai->auth_string_length= (ulong) mpvio->acl_user->auth[mpvio->curr_auth].salt.length;
strmake_buf(ai->authenticated_as, mpvio->acl_user->user.str);
}
/** /**
vio->read_packet() callback method for server authentication plugins vio->read_packet() callback method for server authentication plugins
...@@ -14473,11 +14488,7 @@ static int server_mpvio_read_packet(MYSQL_PLUGIN_VIO *param, uchar **buf) ...@@ -14473,11 +14488,7 @@ static int server_mpvio_read_packet(MYSQL_PLUGIN_VIO *param, uchar **buf)
goto err; goto err;
} }
ai->user_name= ai->thd->security_ctx->user; mpvio_init_auth_info(param, ai);
ai->user_name_length= (uint) strlen(ai->user_name);
ai->auth_string= mpvio->acl_user->auth[mpvio->curr_auth].salt.str;
ai->auth_string_length= (ulong) mpvio->acl_user->auth[mpvio->curr_auth].salt.length;
strmake_buf(ai->authenticated_as, mpvio->acl_user->user.str);
DBUG_RETURN((int)pkt_len); DBUG_RETURN((int)pkt_len);
...@@ -14634,18 +14645,12 @@ static void make_ssl_info(THD *thd, LEX_CSTRING salt, char *info) ...@@ -14634,18 +14645,12 @@ static void make_ssl_info(THD *thd, LEX_CSTRING salt, char *info)
#endif #endif
} }
static int do_auth_once(THD *thd, const LEX_CSTRING *auth_plugin_name, static int do_auth_once(THD *thd, plugin_ref plugin,
MPVIO_EXT *mpvio) MPVIO_EXT *mpvio)
{ {
int res= CR_OK;
bool unlock_plugin= false;
plugin_ref plugin= get_auth_plugin(thd, *auth_plugin_name, &unlock_plugin);
mpvio->plugin= plugin; mpvio->plugin= plugin;
mpvio->auth_info.user_name= NULL; mpvio->auth_info.user_name= NULL;
int res= CR_OK;
if (plugin)
{
st_mysql_auth *info= (st_mysql_auth *) plugin_decl(plugin)->info; st_mysql_auth *info= (st_mysql_auth *) plugin_decl(plugin)->info;
switch (info->interface_version >> 8) { switch (info->interface_version >> 8) {
case 0x02: case 0x02:
...@@ -14662,19 +14667,28 @@ static int do_auth_once(THD *thd, const LEX_CSTRING *auth_plugin_name, ...@@ -14662,19 +14667,28 @@ static int do_auth_once(THD *thd, const LEX_CSTRING *auth_plugin_name,
default: DBUG_ASSERT(0); default: DBUG_ASSERT(0);
} }
if (unlock_plugin) return res;
plugin_unlock(thd, plugin); }
}
else static int do_auth_once(THD *thd, const LEX_CSTRING *auth_plugin_name,
MPVIO_EXT *mpvio)
{
bool unlock_plugin= false;
plugin_ref plugin= get_auth_plugin(thd, *auth_plugin_name, &unlock_plugin);
if (unlikely(!plugin))
{ {
/* Server cannot load the required plugin. */ /* Server cannot load the required plugin. */
Host_errors errors; Host_errors errors;
errors.m_no_auth_plugin= 1; errors.m_no_auth_plugin= 1;
inc_host_errors(mpvio->auth_info.thd->security_ctx->ip, &errors); inc_host_errors(mpvio->auth_info.thd->security_ctx->ip, &errors);
my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), auth_plugin_name->str); my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), auth_plugin_name->str);
res= CR_ERROR; return CR_ERROR;
} }
int res= do_auth_once(thd, plugin, mpvio);
if (unlock_plugin)
plugin_unlock(thd, plugin);
return res; return res;
} }
...@@ -14750,6 +14764,7 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len) ...@@ -14750,6 +14764,7 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
mpvio.auth_info.host_or_ip= thd->security_ctx->host_or_ip; mpvio.auth_info.host_or_ip= thd->security_ctx->host_or_ip;
mpvio.auth_info.host_or_ip_length= mpvio.auth_info.host_or_ip_length=
(unsigned int) strlen(thd->security_ctx->host_or_ip); (unsigned int) strlen(thd->security_ctx->host_or_ip);
mpvio.auth_info.scramble= thd->scramble;
DBUG_PRINT("info", ("com_change_user_pkt_len=%u", com_change_user_pkt_len)); DBUG_PRINT("info", ("com_change_user_pkt_len=%u", com_change_user_pkt_len));
...@@ -14778,7 +14793,7 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len) ...@@ -14778,7 +14793,7 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
the correct plugin. the correct plugin.
*/ */
res= do_auth_once(thd, default_auth_plugin_name, &mpvio); res= do_auth_once(thd, default_auth_plugin, &mpvio);
} }
PSI_CALL_set_connection_type(vio_type(thd->net.vio)); PSI_CALL_set_connection_type(vio_type(thd->net.vio));
......
...@@ -4527,6 +4527,14 @@ static Sys_var_plugin Sys_enforce_storage_engine( ...@@ -4527,6 +4527,14 @@ static Sys_var_plugin Sys_enforce_storage_engine(
DEFAULT(&enforced_storage_engine), NO_MUTEX_GUARD, NOT_IN_BINLOG, DEFAULT(&enforced_storage_engine), NO_MUTEX_GUARD, NOT_IN_BINLOG,
ON_CHECK(check_has_super)); ON_CHECK(check_has_super));
extern const char *default_auth_plugin_name;
extern LEX_CSTRING native_password_plugin_name;
static Sys_var_charptr Sys_default_auth_plugin(
"default_auth_plugin", "Default plugin, that will be tried first when authenticating new connections",
READ_ONLY GLOBAL_VAR(default_auth_plugin_name), CMD_LINE(OPT_ARG),
DEFAULT(native_password_plugin_name.str),
NO_MUTEX_GUARD, NOT_IN_BINLOG);
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
/* /*
......
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