diff --git a/executor/simple.go b/executor/simple.go index 3302410a0007e..6a72297b6d705 100644 --- a/executor/simple.go +++ b/executor/simple.go @@ -176,12 +176,18 @@ func (e *SimpleExec) executeCreateUser(s *ast.CreateUserStmt) error { return errors.Trace(ErrPasswordFormat) } user := fmt.Sprintf(`('%s', '%s', '%s')`, spec.User.Hostname, spec.User.Username, pwd) + if s.IsCreateRole { + user = fmt.Sprintf(`('%s', '%s', '%s', 'Y')`, spec.User.Hostname, spec.User.Username, pwd) + } users = append(users, user) } if len(users) == 0 { return nil } sql := fmt.Sprintf(`INSERT INTO %s.%s (Host, User, Password) VALUES %s;`, mysql.SystemDB, mysql.UserTable, strings.Join(users, ", ")) + if s.IsCreateRole { + sql = fmt.Sprintf(`INSERT INTO %s.%s (Host, User, Password, Account_locked) VALUES %s;`, mysql.SystemDB, mysql.UserTable, strings.Join(users, ", ")) + } _, err := e.ctx.(sqlexec.SQLExecutor).Execute(context.Background(), sql) if err != nil { return errors.Trace(err) diff --git a/go.mod b/go.mod index 1fd151b7e0b22..29584e72dde6b 100644 --- a/go.mod +++ b/go.mod @@ -49,7 +49,7 @@ require ( github.com/pingcap/goleveldb v0.0.0-20171020122428-b9ff6c35079e github.com/pingcap/kvproto v0.0.0-20190215154024-7f2fc73ef562 github.com/pingcap/log v0.0.0-20190214045112-b37da76f67a7 - github.com/pingcap/parser v0.0.0-20190227074025-43073c7d0c79 + github.com/pingcap/parser v0.0.0-20190228070002-74e8cffabf28 github.com/pingcap/pd v2.1.0-rc.4+incompatible github.com/pingcap/tidb-tools v2.1.3-0.20190116051332-34c808eef588+incompatible github.com/pingcap/tipb v0.0.0-20190107072121-abbec73437b7 diff --git a/go.sum b/go.sum index 9e070eb4339e9..b5fddb8c44a48 100644 --- a/go.sum +++ b/go.sum @@ -113,8 +113,8 @@ github.com/pingcap/kvproto v0.0.0-20190215154024-7f2fc73ef562 h1:32oF1/8lVnBR2JV github.com/pingcap/kvproto v0.0.0-20190215154024-7f2fc73ef562/go.mod h1:QMdbTAXCHzzygQzqcG9uVUgU2fKeSN1GmfMiykdSzzY= github.com/pingcap/log v0.0.0-20190214045112-b37da76f67a7 h1:kOHAMalwF69bJrtWrOdVaCSvZjLucrJhP4NQKIu6uM4= github.com/pingcap/log v0.0.0-20190214045112-b37da76f67a7/go.mod h1:xsfkWVaFVV5B8e1K9seWfyJWFrIhbtUTAD8NV1Pq3+w= -github.com/pingcap/parser v0.0.0-20190227074025-43073c7d0c79 h1:i8nl1SmiBtsJRJ1VVxPsFpX1J8O9nhoPOuhfe+60TUE= -github.com/pingcap/parser v0.0.0-20190227074025-43073c7d0c79/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA= +github.com/pingcap/parser v0.0.0-20190228070002-74e8cffabf28 h1:pOOCEgCZHvY4H3kZNZjzru6nZfpbw54QA5EuZWjH/TE= +github.com/pingcap/parser v0.0.0-20190228070002-74e8cffabf28/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA= github.com/pingcap/pd v2.1.0-rc.4+incompatible h1:/buwGk04aHO5odk/+O8ZOXGs4qkUjYTJ2UpCJXna8NE= github.com/pingcap/pd v2.1.0-rc.4+incompatible/go.mod h1:nD3+EoYes4+aNNODO99ES59V83MZSI+dFbhyr667a0E= github.com/pingcap/tidb-tools v2.1.3-0.20190116051332-34c808eef588+incompatible h1:e9Gi/LP9181HT3gBfSOeSBA+5JfemuE4aEAhqNgoE4k= diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index 6205d243bc650..346d853c6e0fe 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -998,7 +998,15 @@ func (b *PlanBuilder) buildSimple(node ast.StmtNode) (Plan, error) { p := &Simple{Statement: node} switch raw := node.(type) { - case *ast.CreateUserStmt, *ast.DropUserStmt, *ast.AlterUserStmt: + case *ast.CreateUserStmt: + if raw.IsCreateRole { + err := ErrSpecificAccessDenied.GenWithStackByArgs("CREATE ROLE") + b.visitInfo = appendVisitInfo(b.visitInfo, mysql.CreateRolePriv, "", "", "", err) + } else { + err := ErrSpecificAccessDenied.GenWithStackByArgs("CREATE USER") + b.visitInfo = appendVisitInfo(b.visitInfo, mysql.CreateUserPriv, "", "", "", err) + } + case *ast.DropUserStmt, *ast.AlterUserStmt: err := ErrSpecificAccessDenied.GenWithStackByArgs("CREATE USER") b.visitInfo = appendVisitInfo(b.visitInfo, mysql.CreateUserPriv, "", "", "", err) case *ast.GrantStmt: diff --git a/privilege/privileges/privileges.go b/privilege/privileges/privileges.go index 6d0b7e71965e3..807359ee79594 100644 --- a/privilege/privileges/privileges.go +++ b/privilege/privileges/privileges.go @@ -113,6 +113,14 @@ func (p *UserPrivileges) ConnectionVerification(user, host string, authenticatio u = record.User h = record.Host + // Login a locked account is not allowed. + locked := record.AccountLocked + if locked { + log.Errorf("Try to login a locked account: user: %v, host: %v", user, host) + success = false + return + } + pwd := record.Password if len(pwd) != 0 && len(pwd) != mysql.PWDHashLen+1 { log.Errorf("User [%s] password from SystemDB not like a sha1sum", user) diff --git a/privilege/privileges/privileges_test.go b/privilege/privileges/privileges_test.go index cf9e7cb28ac70..fdb8a9a8227f6 100644 --- a/privilege/privileges/privileges_test.go +++ b/privilege/privileges/privileges_test.go @@ -299,6 +299,20 @@ func (s *testPrivilegeSuite) TestSelectViewSecurity(c *C) { c.Assert(err.Error(), Equals, core.ErrViewInvalid.GenWithStackByArgs("test", "selectviewsecurity").Error()) } +func (s *testPrivilegeSuite) TestRoleAdminSecurity(c *C) { + se := newSession(c, s.store, s.dbName) + mustExec(c, se, `CREATE USER 'r1'@'localhost';`) + mustExec(c, se, `CREATE USER 'r2'@'localhost';`) + mustExec(c, se, `GRANT ALL ON *.* to r1@localhost`) + + c.Assert(se.Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil), IsTrue) + mustExec(c, se, `create role r_test1@localhost`) + + c.Assert(se.Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil), IsTrue) + _, err := se.Execute(context.Background(), `create role r_test2@localhost`) + c.Assert(terror.ErrorEqual(err, core.ErrSpecificAccessDenied), IsTrue) +} + func (s *testPrivilegeSuite) TestCheckAuthenticate(c *C) { se := newSession(c, s.store, s.dbName) @@ -325,6 +339,18 @@ func (s *testPrivilegeSuite) TestCheckAuthenticate(c *C) { c.Assert(se.Auth(&auth.UserIdentity{Username: "u2", Hostname: "localhost"}, nil, nil), IsFalse) c.Assert(se.Auth(&auth.UserIdentity{Username: "u3@example.com", Hostname: "localhost"}, nil, nil), IsFalse) c.Assert(se.Auth(&auth.UserIdentity{Username: "u4", Hostname: "localhost"}, nil, nil), IsFalse) + + se2 := newSession(c, s.store, s.dbName) + mustExec(c, se2, "create role 'r1'@'localhost'") + mustExec(c, se2, "create role 'r2'@'localhost'") + mustExec(c, se2, "create role 'r3@example.com'@'localhost'") + c.Assert(se.Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil), IsFalse) + c.Assert(se.Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil), IsFalse) + c.Assert(se.Auth(&auth.UserIdentity{Username: "r3@example.com", Hostname: "localhost"}, nil, nil), IsFalse) + + mustExec(c, se1, "drop user 'r1'@'localhost'") + mustExec(c, se1, "drop user 'r2'@'localhost'") + mustExec(c, se1, "drop user 'r3@example.com'@'localhost'") } func (s *testPrivilegeSuite) TestUseDb(c *C) {