diff --git a/executor/simple.go b/executor/simple.go index 4e4e944052f9d..73f6bb395da73 100644 --- a/executor/simple.go +++ b/executor/simple.go @@ -84,8 +84,25 @@ func (e *SimpleExec) Next(ctx context.Context, chk *chunk.Chunk) (err error) { return errors.Trace(err) } +func (e *SimpleExec) dbAccessDenied(dbname string) error { + user := e.ctx.GetSessionVars().User + u := user.Username + h := user.Hostname + if len(user.AuthUsername) > 0 && len(user.AuthHostname) > 0 { + u = user.AuthUsername + h = user.AuthHostname + } + return ErrDBaccessDenied.GenWithStackByArgs(u, h, dbname) +} + func (e *SimpleExec) executeUse(s *ast.UseStmt) error { dbname := model.NewCIStr(s.DBName) + + checker := privilege.GetPrivilegeManager(e.ctx) + if checker != nil && e.ctx.GetSessionVars().User != nil && !checker.DBIsVisible(fmt.Sprint(dbname)) { + return e.dbAccessDenied(dbname.O) + } + dbinfo, exists := e.is.SchemaByName(dbname) if !exists { return infoschema.ErrDatabaseNotExists.GenWithStackByArgs(dbname) diff --git a/privilege/privileges/privileges_test.go b/privilege/privileges/privileges_test.go index 8b0c7dc1687d0..22c71ce98c58c 100644 --- a/privilege/privileges/privileges_test.go +++ b/privilege/privileges/privileges_test.go @@ -323,6 +323,31 @@ func (s *testPrivilegeSuite) TestCheckAuthenticate(c *C) { c.Assert(se.Auth(&auth.UserIdentity{Username: "u4", Hostname: "localhost"}, nil, nil), IsFalse) } +func (s *testPrivilegeSuite) TestUseDb(c *C) { + + se := newSession(c, s.store, s.dbName) + // high privileged user + mustExec(c, se, "CREATE USER 'usesuper'") + mustExec(c, se, "CREATE USER 'usenobody'") + mustExec(c, se, "GRANT ALL ON *.* TO 'usesuper'") + mustExec(c, se, "FLUSH PRIVILEGES") + c.Assert(se.Auth(&auth.UserIdentity{Username: "usesuper", Hostname: "localhost", AuthUsername: "usesuper", AuthHostname: "%"}, nil, nil), IsTrue) + mustExec(c, se, "use mysql") + // low privileged user + c.Assert(se.Auth(&auth.UserIdentity{Username: "usenobody", Hostname: "localhost", AuthUsername: "usenobody", AuthHostname: "%"}, nil, nil), IsTrue) + _, err := se.Execute(context.Background(), "use mysql") + c.Assert(err, NotNil) + + // try again after privilege granted + c.Assert(se.Auth(&auth.UserIdentity{Username: "usesuper", Hostname: "localhost", AuthUsername: "usesuper", AuthHostname: "%"}, nil, nil), IsTrue) + mustExec(c, se, "GRANT SELECT ON mysql.* TO 'usenobody'") + mustExec(c, se, "FLUSH PRIVILEGES") + c.Assert(se.Auth(&auth.UserIdentity{Username: "usenobody", Hostname: "localhost", AuthUsername: "usenobody", AuthHostname: "%"}, nil, nil), IsTrue) + _, err = se.Execute(context.Background(), "use mysql") + c.Assert(err, IsNil) + +} + func (s *testPrivilegeSuite) TestInformationSchema(c *C) { // This test tests no privilege check for INFORMATION_SCHEMA database. diff --git a/server/server_test.go b/server/server_test.go index 7bb5b43635226..e7eed294b7ee2 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -619,13 +619,14 @@ func runTestShowProcessList(c *C) { func runTestAuth(c *C) { runTests(c, nil, func(dbt *DBTest) { dbt.mustExec(`CREATE USER 'authtest'@'%' IDENTIFIED BY '123';`) + dbt.mustExec(`GRANT ALL on test.* to 'authtest'`) dbt.mustExec(`FLUSH PRIVILEGES;`) }) runTests(c, func(config *mysql.Config) { config.User = "authtest" config.Passwd = "123" }, func(dbt *DBTest) { - dbt.mustExec(`USE mysql;`) + dbt.mustExec(`USE information_schema;`) }) db, err := sql.Open("mysql", getDSN(func(config *mysql.Config) { @@ -633,20 +634,21 @@ func runTestAuth(c *C) { config.Passwd = "456" })) c.Assert(err, IsNil) - _, err = db.Query("USE mysql;") + _, err = db.Query("USE information_schema;") c.Assert(err, NotNil, Commentf("Wrong password should be failed")) db.Close() // Test login use IP that not exists in mysql.user. runTests(c, nil, func(dbt *DBTest) { dbt.mustExec(`CREATE USER 'authtest2'@'localhost' IDENTIFIED BY '123';`) + dbt.mustExec(`GRANT ALL on test.* to 'authtest2'@'localhost'`) dbt.mustExec(`FLUSH PRIVILEGES;`) }) runTests(c, func(config *mysql.Config) { config.User = "authtest2" config.Passwd = "123" }, func(dbt *DBTest) { - dbt.mustExec(`USE mysql;`) + dbt.mustExec(`USE information_schema;`) }) } @@ -683,7 +685,9 @@ func runTestIssue3680(c *C) { func runTestIssue3682(c *C) { runTests(c, nil, func(dbt *DBTest) { dbt.mustExec(`CREATE USER 'issue3682'@'%' IDENTIFIED BY '123';`) - dbt.mustExec(`FLUSH PRIVILEGES;`) + dbt.mustExec(`GRANT ALL on test.* to 'issue3682'`) + dbt.mustExec(`GRANT ALL on mysql.* to 'issue3682'`) + dbt.mustExec(`FLUSH PRIVILEGES`) }) runTests(c, func(config *mysql.Config) { config.User = "issue3682"