Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

*: make default_authentication_plugin more compatible with mysql #56660

Merged
merged 4 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions pkg/executor/grant.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/pingcap/tidb/pkg/privilege"
"github.com/pingcap/tidb/pkg/privilege/privileges"
"github.com/pingcap/tidb/pkg/sessionctx"
"github.com/pingcap/tidb/pkg/sessionctx/variable"
"github.com/pingcap/tidb/pkg/sessiontxn"
"github.com/pingcap/tidb/pkg/table"
"github.com/pingcap/tidb/pkg/util"
Expand Down Expand Up @@ -160,14 +161,18 @@ func (e *GrantExec) Next(ctx context.Context, _ *chunk.Chunk) error {
if err != nil {
return err
}
if !exists && e.Ctx().GetSessionVars().SQLMode.HasNoAutoCreateUserMode() {
return exeerrors.ErrCantCreateUserWithGrant
} else if !exists {
if !exists {
if e.Ctx().GetSessionVars().SQLMode.HasNoAutoCreateUserMode() {
return exeerrors.ErrCantCreateUserWithGrant
}
// This code path only applies if mode NO_AUTO_CREATE_USER is unset.
// It is required for compatibility with 5.7 but removed from 8.0
// since it results in a massive security issue:
// spelling errors will create users with no passwords.
authPlugin := mysql.AuthNativePassword
authPlugin, err := e.Ctx().GetSessionVars().GlobalVarsAccessor.GetGlobalSysVar(variable.DefaultAuthPlugin)
if err != nil {
return err
}
if user.AuthOpt != nil && user.AuthOpt.AuthPlugin != "" {
authPlugin = user.AuthOpt.AuthPlugin
}
Expand All @@ -180,7 +185,7 @@ func (e *GrantExec) Next(ctx context.Context, _ *chunk.Chunk) error {
if !ok {
return errors.Trace(exeerrors.ErrPasswordFormat)
}
_, err := internalSession.GetSQLExecutor().ExecuteInternal(internalCtx,
_, err = internalSession.GetSQLExecutor().ExecuteInternal(internalCtx,
`INSERT INTO %n.%n (Host, User, authentication_string, plugin) VALUES (%?, %?, %?, %?);`,
mysql.SystemDB, mysql.UserTable, user.User.Hostname, user.User.Username, pwd, authPlugin)
if err != nil {
Expand Down
11 changes: 7 additions & 4 deletions pkg/executor/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -1761,9 +1761,12 @@ func (e *ShowExec) fetchShowCreateUser(ctx context.Context) error {
fmt.Sprintf("'%s'@'%s'", e.User.Username, e.User.Hostname))
}

authplugin := mysql.AuthNativePassword
authPlugin, err := e.Ctx().GetSessionVars().GlobalVarsAccessor.GetGlobalSysVar(variable.DefaultAuthPlugin)
if err != nil {
return errors.Trace(err)
}
if len(rows) == 1 && rows[0].GetString(0) != "" {
authplugin = rows[0].GetString(0)
authPlugin = rows[0].GetString(0)
}

accountLockedRaw := rows[0].GetString(1)
Expand Down Expand Up @@ -1841,13 +1844,13 @@ func (e *ShowExec) fetchShowCreateUser(ctx context.Context) error {

authData := checker.GetEncodedPassword(e.User.Username, e.User.Hostname)
authStr := ""
if !(authplugin == mysql.AuthSocket && authData == "") {
if !(authPlugin == mysql.AuthSocket && authData == "") {
authStr = fmt.Sprintf(" AS '%s'", authData)
}

// FIXME: the returned string is not escaped safely
showStr := fmt.Sprintf("CREATE USER '%s'@'%s' IDENTIFIED WITH '%s'%s REQUIRE %s%s %s ACCOUNT %s PASSWORD HISTORY %s PASSWORD REUSE INTERVAL %s%s%s%s",
e.User.Username, e.User.Hostname, authplugin, authStr, require, tokenIssuer, passwordExpiredStr, accountLocked, passwordHistory, passwordReuseInterval, failedLoginAttempts, passwordLockTimeDays, userAttributes)
e.User.Username, e.User.Hostname, authPlugin, authStr, require, tokenIssuer, passwordExpiredStr, accountLocked, passwordHistory, passwordReuseInterval, failedLoginAttempts, passwordLockTimeDays, userAttributes)
e.appendRow([]any{showStr})
return nil
}
Expand Down
6 changes: 5 additions & 1 deletion pkg/executor/simple.go
Original file line number Diff line number Diff line change
Expand Up @@ -1110,6 +1110,10 @@ func (e *SimpleExec) executeCreateUser(ctx context.Context, s *ast.CreateUserStm
if savePasswdHistory {
sqlescape.MustFormatSQL(sqlPasswordHistory, `INSERT INTO %n.%n (Host, User, Password) VALUES `, mysql.SystemDB, mysql.PasswordHistoryTable)
}
defaultAuthPlugin, err := e.Ctx().GetSessionVars().GlobalVarsAccessor.GetGlobalSysVar(variable.DefaultAuthPlugin)
if err != nil {
return errors.Trace(err)
}

users := make([]*auth.UserIdentity, 0, len(s.Specs))
for _, spec := range s.Specs {
Expand Down Expand Up @@ -1141,7 +1145,7 @@ func (e *SimpleExec) executeCreateUser(ctx context.Context, s *ast.CreateUserStm
e.Ctx().GetSessionVars().StmtCtx.AppendNote(err)
continue
}
authPlugin := mysql.AuthNativePassword
authPlugin := defaultAuthPlugin
if spec.AuthOpt != nil && spec.AuthOpt.AuthPlugin != "" {
authPlugin = spec.AuthOpt.AuthPlugin
}
Expand Down
60 changes: 60 additions & 0 deletions tests/integrationtest/r/executor/simple.result
Original file line number Diff line number Diff line change
Expand Up @@ -454,3 +454,63 @@ id
1
2
set autocommit = default;
set global default_authentication_plugin = 'invalid_auth_plugin';
Error 1231 (42000): Variable 'default_authentication_plugin' can't be set to the value of 'invalid_auth_plugin'
set global default_authentication_plugin = 'auth_socket';
Error 1231 (42000): Variable 'default_authentication_plugin' can't be set to the value of 'auth_socket'
set global default_authentication_plugin = 'tidb_sm3_password';
create user default_sm3_user;
show create user default_sm3_user;
CREATE USER for default_sm3_user@%
CREATE USER 'default_sm3_user'@'%' IDENTIFIED WITH 'tidb_sm3_password' AS '' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK PASSWORD HISTORY DEFAULT PASSWORD REUSE INTERVAL DEFAULT
select plugin from mysql.user where user = 'default_sm3_user';
plugin
tidb_sm3_password
set global default_authentication_plugin = 'caching_sha2_password';
create user default_sha2_user;
create user native_plugin_user identified with 'mysql_native_password';
create role default_sha2_role;
show create user default_sha2_user;
CREATE USER for default_sha2_user@%
CREATE USER 'default_sha2_user'@'%' IDENTIFIED WITH 'caching_sha2_password' AS '' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK PASSWORD HISTORY DEFAULT PASSWORD REUSE INTERVAL DEFAULT
select plugin from mysql.user where user = 'default_sha2_user';
plugin
caching_sha2_password
show create user native_plugin_user;
CREATE USER for native_plugin_user@%
CREATE USER 'native_plugin_user'@'%' IDENTIFIED WITH 'mysql_native_password' AS '' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK PASSWORD HISTORY DEFAULT PASSWORD REUSE INTERVAL DEFAULT
select plugin from mysql.user where user = 'native_plugin_user';
plugin
mysql_native_password
show create user default_sha2_role;
CREATE USER for default_sha2_role@%
CREATE USER 'default_sha2_role'@'%' IDENTIFIED WITH 'caching_sha2_password' AS '' REQUIRE NONE PASSWORD EXPIRE ACCOUNT LOCK PASSWORD HISTORY DEFAULT PASSWORD REUSE INTERVAL DEFAULT
select plugin from mysql.user where user = 'default_sha2_role';
plugin
caching_sha2_password
alter user default_sha2_user identified with 'tidb_sm3_password';
show create user default_sha2_user;
CREATE USER for default_sha2_user@%
CREATE USER 'default_sha2_user'@'%' IDENTIFIED WITH 'tidb_sm3_password' AS '' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK PASSWORD HISTORY DEFAULT PASSWORD REUSE INTERVAL DEFAULT
select plugin from mysql.user where user = 'default_sha2_user';
plugin
tidb_sm3_password
alter user default_sha2_user identified with 'authentication_ldap_simple';
show create user default_sha2_user;
CREATE USER for default_sha2_user@%
CREATE USER 'default_sha2_user'@'%' IDENTIFIED WITH 'authentication_ldap_simple' AS '' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK PASSWORD HISTORY DEFAULT PASSWORD REUSE INTERVAL DEFAULT
select plugin from mysql.user where user = 'default_sha2_user';
plugin
authentication_ldap_simple
alter user default_sha2_user identified with 'authentication_ldap_sasl';
show create user default_sha2_user;
CREATE USER for default_sha2_user@%
CREATE USER 'default_sha2_user'@'%' IDENTIFIED WITH 'authentication_ldap_sasl' AS '' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK PASSWORD HISTORY DEFAULT PASSWORD REUSE INTERVAL DEFAULT
select plugin from mysql.user where user = 'default_sha2_user';
plugin
authentication_ldap_sasl
drop user default_sm3_user;
drop user default_sha2_user;
drop user native_plugin_user;
drop user default_sha2_role;
set global default_authentication_plugin = default;
43 changes: 43 additions & 0 deletions tests/integrationtest/t/executor/simple.test
Original file line number Diff line number Diff line change
Expand Up @@ -487,3 +487,46 @@ rollback;
select * from auto_new;

set autocommit = default;

# TestDefaultAuthPluginForCreateUser

connection default;

--error 1231
set global default_authentication_plugin = 'invalid_auth_plugin';
--error 1231
set global default_authentication_plugin = 'auth_socket';

set global default_authentication_plugin = 'tidb_sm3_password';
create user default_sm3_user;
show create user default_sm3_user;
select plugin from mysql.user where user = 'default_sm3_user';

set global default_authentication_plugin = 'caching_sha2_password';
Copy link
Contributor

@dveeden dveeden Oct 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add something like set global default_authentication_plugin = 'xxxxx' to test the validation of the plugin name?

Maybe add statements like CREATE USER ... IDENTIFIED WITH ... to test if you can still create users with mysql_native_plugin when the default_authentication_plugin is set to caching_sha2_password?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated in fa4a9a1

create user default_sha2_user;
create user native_plugin_user identified with 'mysql_native_password';
create role default_sha2_role;
show create user default_sha2_user;
select plugin from mysql.user where user = 'default_sha2_user';
show create user native_plugin_user;
select plugin from mysql.user where user = 'native_plugin_user';
show create user default_sha2_role;
select plugin from mysql.user where user = 'default_sha2_role';

alter user default_sha2_user identified with 'tidb_sm3_password';
show create user default_sha2_user;
select plugin from mysql.user where user = 'default_sha2_user';

alter user default_sha2_user identified with 'authentication_ldap_simple';
show create user default_sha2_user;
select plugin from mysql.user where user = 'default_sha2_user';

alter user default_sha2_user identified with 'authentication_ldap_sasl';
show create user default_sha2_user;
select plugin from mysql.user where user = 'default_sha2_user';

drop user default_sm3_user;
drop user default_sha2_user;
drop user native_plugin_user;
drop user default_sha2_role;
set global default_authentication_plugin = default;