diff --git a/executor/grant_test.go b/executor/grant_test.go index 8ccfac3533fb6..df45169b23ff5 100644 --- a/executor/grant_test.go +++ b/executor/grant_test.go @@ -366,6 +366,14 @@ func (s *testSuite3) TestMaintainRequire(c *C) { c.Assert(err, NotNil) } +func (s *testSuite3) TestMaintainAuthString(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec(`CREATE USER 'maint_auth_str1'@'%' IDENTIFIED BY 'foo'`) + tk.MustQuery("SELECT authentication_string FROM mysql.user WHERE `Host` = '%' and `User` = 'maint_auth_str1'").Check(testkit.Rows("*F3A2A51A9B0F2BE2468926B4132313728C250DBF")) + tk.MustExec(`ALTER USER 'maint_auth_str1'@'%' REQUIRE SSL`) + tk.MustQuery("SELECT authentication_string FROM mysql.user WHERE `Host` = '%' and `User` = 'maint_auth_str1'").Check(testkit.Rows("*F3A2A51A9B0F2BE2468926B4132313728C250DBF")) +} + func (s *testSuite3) TestGrantOnNonExistTable(c *C) { tk := testkit.NewTestKit(c, s.store) tk.MustExec("create user genius") diff --git a/executor/simple.go b/executor/simple.go index 95067f42621d0..3d21e150c2b3b 100644 --- a/executor/simple.go +++ b/executor/simple.go @@ -848,10 +848,16 @@ func (e *SimpleExec) executeAlterUser(s *ast.AlterUserStmt) error { failedUsers := make([]string, 0, len(s.Specs)) for _, spec := range s.Specs { - if spec.User.CurrentUser { - user := e.ctx.GetSessionVars().User + user := e.ctx.GetSessionVars().User + if spec.User.CurrentUser || ((user != nil) && (user.Username == spec.User.Username) && (user.AuthHostname == spec.User.Hostname)) { spec.User.Username = user.Username spec.User.Hostname = user.AuthHostname + } else { + checker := privilege.GetPrivilegeManager(e.ctx) + activeRoles := e.ctx.GetSessionVars().ActiveRoles + if checker != nil && !checker.RequestVerification(activeRoles, "", "", "", mysql.SuperPriv) { + return ErrDBaccessDenied.GenWithStackByArgs(spec.User.Username, spec.User.Hostname, "mysql") + } } exists, err := userExists(e.ctx, spec.User.Username, spec.User.Hostname) @@ -863,22 +869,25 @@ func (e *SimpleExec) executeAlterUser(s *ast.AlterUserStmt) error { failedUsers = append(failedUsers, user) continue } - pwd, ok := spec.EncodedPassword() - if !ok { - return errors.Trace(ErrPasswordFormat) - } + exec := e.ctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(context.TODO(), `UPDATE %n.%n SET authentication_string=%? WHERE Host=%? and User=%?;`, mysql.SystemDB, mysql.UserTable, pwd, spec.User.Hostname, spec.User.Username) - if err != nil { - return err - } - _, _, err = exec.ExecRestrictedStmt(context.TODO(), stmt) - if err != nil { - failedUsers = append(failedUsers, spec.User.String()) + if spec.AuthOpt != nil { + pwd, ok := spec.EncodedPassword() + if !ok { + return errors.Trace(ErrPasswordFormat) + } + stmt, err := exec.ParseWithParams(context.TODO(), `UPDATE %n.%n SET authentication_string=%? WHERE Host=%? and User=%?;`, mysql.SystemDB, mysql.UserTable, pwd, spec.User.Hostname, spec.User.Username) + if err != nil { + return err + } + _, _, err = exec.ExecRestrictedStmt(context.TODO(), stmt) + if err != nil { + failedUsers = append(failedUsers, spec.User.String()) + } } if len(privData) > 0 { - stmt, err = exec.ParseWithParams(context.TODO(), "INSERT INTO %n.%n (Host, User, Priv) VALUES (%?,%?,%?) ON DUPLICATE KEY UPDATE Priv = values(Priv)", mysql.SystemDB, mysql.GlobalPrivTable, spec.User.Hostname, spec.User.Username, string(hack.String(privData))) + stmt, err := exec.ParseWithParams(context.TODO(), "INSERT INTO %n.%n (Host, User, Priv) VALUES (%?,%?,%?) ON DUPLICATE KEY UPDATE Priv = values(Priv)", mysql.SystemDB, mysql.GlobalPrivTable, spec.User.Hostname, spec.User.Username, string(hack.String(privData))) if err != nil { return err } diff --git a/privilege/privileges/privileges_test.go b/privilege/privileges/privileges_test.go index 1bb69be14c826..4d0b42a6d37ff 100644 --- a/privilege/privileges/privileges_test.go +++ b/privilege/privileges/privileges_test.go @@ -468,6 +468,28 @@ func (s *testPrivilegeSuite) TestSetPasswdStmt(c *C) { c.Assert(err, NotNil) } +func (s *testPrivilegeSuite) TestAlterUserStmt(c *C) { + se := newSession(c, s.store, s.dbName) + + // high privileged user setting password for other user (passes) + mustExec(c, se, "CREATE USER 'superuser2'") + mustExec(c, se, "CREATE USER 'nobodyuser2'") + mustExec(c, se, "CREATE USER 'nobodyuser3'") + mustExec(c, se, "GRANT ALL ON *.* TO 'superuser2'") + mustExec(c, se, "GRANT CREATE USER ON *.* TO 'nobodyuser2'") + + c.Assert(se.Auth(&auth.UserIdentity{Username: "superuser2", Hostname: "localhost", AuthUsername: "superuser2", AuthHostname: "%"}, nil, nil), IsTrue) + mustExec(c, se, "ALTER USER 'nobodyuser2' IDENTIFIED BY 'newpassword'") + mustExec(c, se, "ALTER USER 'nobodyuser2' IDENTIFIED BY ''") + + // low privileged user trying to set password for other user (fails) + c.Assert(se.Auth(&auth.UserIdentity{Username: "nobodyuser2", Hostname: "localhost", AuthUsername: "nobodyuser2", AuthHostname: "%"}, nil, nil), IsTrue) + mustExec(c, se, "ALTER USER 'nobodyuser2' IDENTIFIED BY 'newpassword'") + mustExec(c, se, "ALTER USER 'nobodyuser2' IDENTIFIED BY ''") + _, err := se.ExecuteInternal(context.Background(), "ALTER USER 'superuser2' IDENTIFIED BY 'newpassword'") + c.Assert(err, NotNil) +} + func (s *testPrivilegeSuite) TestSelectViewSecurity(c *C) { se := newSession(c, s.store, s.dbName) ctx, _ := se.(sessionctx.Context)