Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
39 changes: 39 additions & 0 deletions tests/integrationtest/r/executor/simple.result
Original file line number Diff line number Diff line change
Expand Up @@ -454,3 +454,42 @@ id
1
2
set autocommit = default;
set global default_authentication_plugin = 'caching_sha2_password';
create user default_sha256_user;
create role default_sha256_role;
show create user default_sha256_user;
CREATE USER for default_sha256_user@%
CREATE USER 'default_sha256_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_sha256_user';
plugin
caching_sha2_password
show create user default_sha256_role;
CREATE USER for default_sha256_role@%
CREATE USER 'default_sha256_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_sha256_role';
plugin
caching_sha2_password
alter user default_sha256_user identified with 'tidb_sm3_password';
show create user default_sha256_user;
CREATE USER for default_sha256_user@%
CREATE USER 'default_sha256_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_sha256_user';
plugin
tidb_sm3_password
alter user default_sha256_user identified with 'authentication_ldap_simple';
show create user default_sha256_user;
CREATE USER for default_sha256_user@%
CREATE USER 'default_sha256_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_sha256_user';
plugin
authentication_ldap_simple
alter user default_sha256_user identified with 'authentication_ldap_sasl';
show create user default_sha256_user;
CREATE USER for default_sha256_user@%
CREATE USER 'default_sha256_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_sha256_user';
plugin
authentication_ldap_sasl
drop user default_sha256_user;
drop user default_sha256_role;
set global default_authentication_plugin = default;
27 changes: 27 additions & 0 deletions tests/integrationtest/t/executor/simple.test
Original file line number Diff line number Diff line change
Expand Up @@ -487,3 +487,30 @@ rollback;
select * from auto_new;

set autocommit = default;

# TestDefaultAuthPluginForCreateUser

connection default;
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_sha256_user;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the sha256 is confusing here as there used to be a sha256_password plugin.

Suggested change
create user default_sha256_user;
create user default_sha2_user;

(more modifications needed if you merge this)

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 role default_sha256_role;
show create user default_sha256_user;
select plugin from mysql.user where user = 'default_sha256_user';
show create user default_sha256_role;
select plugin from mysql.user where user = 'default_sha256_role';

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

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

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

drop user default_sha256_user;
drop user default_sha256_role;
set global default_authentication_plugin = default;