Skip to content

Commit

Permalink
privilege: fix REVOKE privilege check incompatibility with MySQL (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
sre-bot committed Dec 11, 2019
1 parent ce88d7b commit 3a10bb8
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 3 deletions.
15 changes: 13 additions & 2 deletions planner/core/logical_plan_test.go
Expand Up @@ -1759,9 +1759,20 @@ func (s *testPlanSuite) TestVisitInfo(c *C) {
},
},
{
sql: `revoke all privileges on *.* from 'test'@'%'`,
sql: `revoke all privileges on test.* from 'test'@'%'`,
ans: []visitInfo{
{mysql.SuperPriv, "", "", "", nil},
{mysql.SelectPriv, "test", "", "", nil},
{mysql.InsertPriv, "test", "", "", nil},
{mysql.UpdatePriv, "test", "", "", nil},
{mysql.DeletePriv, "test", "", "", nil},
{mysql.CreatePriv, "test", "", "", nil},
{mysql.DropPriv, "test", "", "", nil},
{mysql.GrantPriv, "test", "", "", nil},
{mysql.AlterPriv, "test", "", "", nil},
{mysql.ExecutePriv, "test", "", "", nil},
{mysql.IndexPriv, "test", "", "", nil},
{mysql.CreateViewPriv, "test", "", "", nil},
{mysql.ShowViewPriv, "test", "", "", nil},
},
},
{
Expand Down
35 changes: 34 additions & 1 deletion planner/core/planbuilder.go
Expand Up @@ -1369,7 +1369,7 @@ func (b *PlanBuilder) buildSimple(node ast.StmtNode) (Plan, error) {
err := ErrSpecificAccessDenied.GenWithStackByArgs("SUPER")
b.visitInfo = appendVisitInfo(b.visitInfo, mysql.SuperPriv, "", "", "", err)
case *ast.RevokeStmt:
b.visitInfo = appendVisitInfo(b.visitInfo, mysql.SuperPriv, "", "", "", nil)
b.visitInfo = collectVisitInfoFromRevokeStmt(b.ctx, b.visitInfo, raw)
case *ast.RevokeRoleStmt:
err := ErrSpecificAccessDenied.GenWithStackByArgs("SUPER")
b.visitInfo = appendVisitInfo(b.visitInfo, mysql.SuperPriv, "", "", "", err)
Expand All @@ -1393,6 +1393,39 @@ func (b *PlanBuilder) buildSimple(node ast.StmtNode) (Plan, error) {
return p, nil
}

func collectVisitInfoFromRevokeStmt(sctx sessionctx.Context, vi []visitInfo, stmt *ast.RevokeStmt) []visitInfo {
// To use REVOKE, you must have the GRANT OPTION privilege,
// and you must have the privileges that you are granting.
dbName := stmt.Level.DBName
tableName := stmt.Level.TableName
if dbName == "" {
dbName = sctx.GetSessionVars().CurrentDB
}
vi = appendVisitInfo(vi, mysql.GrantPriv, dbName, tableName, "", nil)

var allPrivs []mysql.PrivilegeType
for _, item := range stmt.Privs {
if item.Priv == mysql.AllPriv {
switch stmt.Level.Level {
case ast.GrantLevelGlobal:
allPrivs = mysql.AllGlobalPrivs
case ast.GrantLevelDB:
allPrivs = mysql.AllDBPrivs
case ast.GrantLevelTable:
allPrivs = mysql.AllTablePrivs
}
break
}
vi = appendVisitInfo(vi, item.Priv, dbName, tableName, "", nil)
}

for _, priv := range allPrivs {
vi = appendVisitInfo(vi, priv, dbName, tableName, "", nil)
}

return vi
}

func collectVisitInfoFromGrantStmt(sctx sessionctx.Context, vi []visitInfo, stmt *ast.GrantStmt) []visitInfo {
// To use GRANT, you must have the GRANT OPTION privilege,
// and you must have the privileges that you are granting.
Expand Down
18 changes: 18 additions & 0 deletions privilege/privileges/privileges_test.go
Expand Up @@ -541,6 +541,24 @@ func (s *testPrivilegeSuite) TestUseDB(c *C) {
c.Assert(err, NotNil)
}

func (s *testPrivilegeSuite) TestRevokePrivileges(c *C) {
se := newSession(c, s.store, s.dbName)
mustExec(c, se, "CREATE USER 'hasgrant'")
mustExec(c, se, "CREATE USER 'withoutgrant'")
mustExec(c, se, "GRANT ALL ON *.* TO 'hasgrant'")
mustExec(c, se, "GRANT ALL ON mysql.* TO 'withoutgrant'")
// Without grant option
c.Assert(se.Auth(&auth.UserIdentity{Username: "hasgrant", Hostname: "localhost", AuthUsername: "hasgrant", AuthHostname: "%"}, nil, nil), IsTrue)
_, e := se.Execute(context.Background(), "REVOKE SELECT ON mysql.* FROM 'withoutgrant'")
c.Assert(e, NotNil)
// With grant option
se = newSession(c, s.store, s.dbName)
mustExec(c, se, "GRANT ALL ON *.* TO 'hasgrant' WITH GRANT OPTION")
c.Assert(se.Auth(&auth.UserIdentity{Username: "hasgrant", Hostname: "localhost", AuthUsername: "hasgrant", AuthHostname: "%"}, nil, nil), IsTrue)
mustExec(c, se, "REVOKE SELECT ON mysql.* FROM 'withoutgrant'")
mustExec(c, se, "REVOKE ALL ON mysql.* FROM withoutgrant")
}

func (s *testPrivilegeSuite) TestSetGlobal(c *C) {
se := newSession(c, s.store, s.dbName)
mustExec(c, se, `CREATE USER setglobal_a@localhost`)
Expand Down

0 comments on commit 3a10bb8

Please sign in to comment.