Skip to content

Commit

Permalink
executor: Escape object in show grants output (pingcap#46976)
Browse files Browse the repository at this point in the history
  • Loading branch information
sunxiaoguang authored Sep 20, 2023
1 parent 4edb78e commit 6271d1c
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 60 deletions.
4 changes: 2 additions & 2 deletions executor/test/showtest/show_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -917,8 +917,8 @@ func TestIssue10549(t *testing.T) {

require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "dev", Hostname: "%", AuthUsername: "dev", AuthHostname: "%"}, nil, nil, nil))
tk.MustQuery("SHOW DATABASES;").Check(testkit.Rows("INFORMATION_SCHEMA", "newdb"))
tk.MustQuery("SHOW GRANTS;").Check(testkit.Rows("GRANT USAGE ON *.* TO 'dev'@'%'", "GRANT ALL PRIVILEGES ON newdb.* TO 'dev'@'%'", "GRANT 'app_developer'@'%' TO 'dev'@'%'"))
tk.MustQuery("SHOW GRANTS FOR CURRENT_USER").Check(testkit.Rows("GRANT USAGE ON *.* TO 'dev'@'%'", "GRANT ALL PRIVILEGES ON newdb.* TO 'dev'@'%'", "GRANT 'app_developer'@'%' TO 'dev'@'%'"))
tk.MustQuery("SHOW GRANTS;").Check(testkit.Rows("GRANT USAGE ON *.* TO 'dev'@'%'", "GRANT ALL PRIVILEGES ON `newdb`.* TO 'dev'@'%'", "GRANT 'app_developer'@'%' TO 'dev'@'%'"))
tk.MustQuery("SHOW GRANTS FOR CURRENT_USER").Check(testkit.Rows("GRANT USAGE ON *.* TO 'dev'@'%'", "GRANT ALL PRIVILEGES ON `newdb`.* TO 'dev'@'%'", "GRANT 'app_developer'@'%' TO 'dev'@'%'"))
tk.MustQuery("SHOW GRANTS FOR dev").Check(testkit.Rows("GRANT USAGE ON *.* TO 'dev'@'%'", "GRANT 'app_developer'@'%' TO 'dev'@'%'"))
}

Expand Down
6 changes: 3 additions & 3 deletions executor/test/simpletest/simple_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,9 +264,9 @@ func TestPrivilegesAfterDropUser(t *testing.T) {
tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)
tk.MustQuery("SHOW GRANTS FOR u1").Check(testkit.Rows(
"GRANT USAGE ON *.* TO 'u1'@'%'",
"GRANT CREATE ON test.* TO 'u1'@'%'",
"GRANT UPDATE ON test.t1 TO 'u1'@'%'",
"GRANT SELECT(v), UPDATE(v) ON test.t1 TO 'u1'@'%'",
"GRANT CREATE ON `test`.* TO 'u1'@'%'",
"GRANT UPDATE ON `test`.`t1` TO 'u1'@'%'",
"GRANT SELECT(v), UPDATE(v) ON `test`.`t1` TO 'u1'@'%'",
"GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO 'u1'@'%'",
))

Expand Down
16 changes: 10 additions & 6 deletions privilege/privileges/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -1247,7 +1247,7 @@ func (p *MySQLPrivilege) DBIsVisible(user, host, db string) bool {
return false
}

func (p *MySQLPrivilege) showGrants(user, host string, roles []*auth.RoleIdentity) []string {
func (p *MySQLPrivilege) showGrants(ctx sessionctx.Context, user, host string, roles []*auth.RoleIdentity) []string {
var gs []string //nolint: prealloc
var sortFromIdx int
var hasGlobalGrant = false
Expand Down Expand Up @@ -1319,7 +1319,10 @@ func (p *MySQLPrivilege) showGrants(user, host string, roles []*auth.RoleIdentit
}
}
}

sqlMode := ctx.GetSessionVars().SQLMode
for dbName, priv := range dbPrivTable {
dbName = stringutil.Escape(dbName, sqlMode)
g := dbPrivToString(priv)
if len(g) > 0 {
var s string
Expand All @@ -1342,7 +1345,7 @@ func (p *MySQLPrivilege) showGrants(user, host string, roles []*auth.RoleIdentit
sortFromIdx = len(gs)
tablePrivTable := make(map[string]mysql.PrivilegeType)
for _, record := range p.TablesPriv {
recordKey := record.DB + "." + record.TableName
recordKey := stringutil.Escape(record.DB, sqlMode) + "." + stringutil.Escape(record.TableName, sqlMode)
if user == record.User && host == record.Host {
tablePrivTable[recordKey] |= record.TablePriv
} else {
Expand Down Expand Up @@ -1378,9 +1381,9 @@ func (p *MySQLPrivilege) showGrants(user, host string, roles []*auth.RoleIdentit
columnPrivTable := make(map[string]privOnColumns)
for i := range p.ColumnsPriv {
record := p.ColumnsPriv[i]
if !collectColumnGrant(&record, user, host, columnPrivTable) {
if !collectColumnGrant(&record, user, host, columnPrivTable, sqlMode) {
for _, r := range allRoles {
collectColumnGrant(&record, r.Username, r.Hostname, columnPrivTable)
collectColumnGrant(&record, r.Username, r.Hostname, columnPrivTable, sqlMode)
}
}
}
Expand Down Expand Up @@ -1491,9 +1494,10 @@ func privOnColumnsToString(p privOnColumns) string {
return buf.String()
}

func collectColumnGrant(record *columnsPrivRecord, user, host string, columnPrivTable map[string]privOnColumns) bool {
func collectColumnGrant(record *columnsPrivRecord, user, host string, columnPrivTable map[string]privOnColumns, sqlMode mysql.SQLMode) bool {
if record.baseRecord.match(user, host) {
recordKey := record.DB + "." + record.TableName
recordKey := stringutil.Escape(record.DB, sqlMode) + "." + stringutil.Escape(record.TableName, sqlMode)

privColumns, ok := columnPrivTable[recordKey]
if !ok {
privColumns = make(map[mysql.PrivilegeType]columnStrs)
Expand Down
2 changes: 1 addition & 1 deletion privilege/privileges/privileges.go
Original file line number Diff line number Diff line change
Expand Up @@ -842,7 +842,7 @@ func (p *UserPrivileges) ShowGrants(ctx sessionctx.Context, user *auth.UserIdent
u = user.AuthUsername
h = user.AuthHostname
}
grants = mysqlPrivilege.showGrants(u, h, roles)
grants = mysqlPrivilege.showGrants(ctx, u, h, roles)
if len(grants) == 0 {
err = ErrNonexistingGrant.GenWithStackByArgs(u, h)
}
Expand Down
102 changes: 65 additions & 37 deletions privilege/privileges/privileges_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,16 +295,16 @@ func TestShowGrants(t *testing.T) {
require.NoError(t, err)
require.Len(t, gs, 2)
expected := []string{`GRANT ALL PRIVILEGES ON *.* TO 'show'@'localhost'`,
`GRANT SELECT ON test.* TO 'show'@'localhost'`}
"GRANT SELECT ON `test`.* TO 'show'@'localhost'"}
require.True(t, testutil.CompareUnorderedStringSlice(gs, expected), fmt.Sprintf("gs: %v, expected: %v", gs, expected))

tk.MustExec(`GRANT Index ON test1.* TO 'show'@'localhost';`)
gs, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil)
require.NoError(t, err)
require.Len(t, gs, 3)
expected = []string{`GRANT ALL PRIVILEGES ON *.* TO 'show'@'localhost'`,
`GRANT SELECT ON test.* TO 'show'@'localhost'`,
`GRANT INDEX ON test1.* TO 'show'@'localhost'`}
"GRANT SELECT ON `test`.* TO 'show'@'localhost'",
"GRANT INDEX ON `test1`.* TO 'show'@'localhost'"}
require.True(t, testutil.CompareUnorderedStringSlice(gs, expected), fmt.Sprintf("gs: %v, expected: %v", gs, expected))

// Add another db privilege to the same db and test again.
Expand All @@ -313,17 +313,17 @@ func TestShowGrants(t *testing.T) {
require.NoError(t, err)
require.Len(t, gs, 3)
expected = []string{`GRANT ALL PRIVILEGES ON *.* TO 'show'@'localhost'`,
`GRANT SELECT ON test.* TO 'show'@'localhost'`,
`GRANT DELETE,INDEX ON test1.* TO 'show'@'localhost'`}
"GRANT SELECT ON `test`.* TO 'show'@'localhost'",
"GRANT DELETE,INDEX ON `test1`.* TO 'show'@'localhost'"}
require.True(t, testutil.CompareUnorderedStringSlice(gs, expected), fmt.Sprintf("gs: %v, expected: %v", gs, expected))

tk.MustExec(`GRANT ALL ON test1.* TO 'show'@'localhost';`)
gs, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil)
require.NoError(t, err)
require.Len(t, gs, 3)
expected = []string{`GRANT ALL PRIVILEGES ON *.* TO 'show'@'localhost'`,
`GRANT SELECT ON test.* TO 'show'@'localhost'`,
`GRANT ALL PRIVILEGES ON test1.* TO 'show'@'localhost'`}
"GRANT SELECT ON `test`.* TO 'show'@'localhost'",
"GRANT ALL PRIVILEGES ON `test1`.* TO 'show'@'localhost'"}
require.True(t, testutil.CompareUnorderedStringSlice(gs, expected), fmt.Sprintf("gs: %v, expected: %v", gs, expected))

// Add table scope privileges
Expand All @@ -332,9 +332,9 @@ func TestShowGrants(t *testing.T) {
require.NoError(t, err)
require.Len(t, gs, 4)
expected = []string{`GRANT ALL PRIVILEGES ON *.* TO 'show'@'localhost'`,
`GRANT SELECT ON test.* TO 'show'@'localhost'`,
`GRANT ALL PRIVILEGES ON test1.* TO 'show'@'localhost'`,
`GRANT UPDATE ON test.test TO 'show'@'localhost'`}
"GRANT SELECT ON `test`.* TO 'show'@'localhost'",
"GRANT ALL PRIVILEGES ON `test1`.* TO 'show'@'localhost'",
"GRANT UPDATE ON `test`.`test` TO 'show'@'localhost'"}
require.True(t, testutil.CompareUnorderedStringSlice(gs, expected), fmt.Sprintf("gs: %v, expected: %v", gs, expected))

// Revoke the db privilege of `test` and test again. See issue #30855.
Expand All @@ -343,8 +343,8 @@ func TestShowGrants(t *testing.T) {
require.NoError(t, err)
require.Len(t, gs, 3)
expected = []string{`GRANT ALL PRIVILEGES ON *.* TO 'show'@'localhost'`,
`GRANT ALL PRIVILEGES ON test1.* TO 'show'@'localhost'`,
`GRANT UPDATE ON test.test TO 'show'@'localhost'`}
"GRANT ALL PRIVILEGES ON `test1`.* TO 'show'@'localhost'",
"GRANT UPDATE ON `test`.`test` TO 'show'@'localhost'"}
require.True(t, testutil.CompareUnorderedStringSlice(gs, expected), fmt.Sprintf("gs: %v, expected: %v", gs, expected))

// Add another table privilege and test again.
Expand All @@ -353,8 +353,8 @@ func TestShowGrants(t *testing.T) {
require.NoError(t, err)
require.Len(t, gs, 3)
expected = []string{`GRANT ALL PRIVILEGES ON *.* TO 'show'@'localhost'`,
`GRANT ALL PRIVILEGES ON test1.* TO 'show'@'localhost'`,
`GRANT SELECT,UPDATE ON test.test TO 'show'@'localhost'`}
"GRANT ALL PRIVILEGES ON `test1`.* TO 'show'@'localhost'",
"GRANT SELECT,UPDATE ON `test`.`test` TO 'show'@'localhost'"}
require.True(t, testutil.CompareUnorderedStringSlice(gs, expected), fmt.Sprintf("gs: %v, expected: %v", gs, expected))

// Expected behavior: Usage still exists after revoking all privileges
Expand Down Expand Up @@ -455,7 +455,7 @@ func TestShowColumnGrants(t *testing.T) {
pc := privilege.GetPrivilegeManager(tk.Session())
gs, err := pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "column", Hostname: "%"}, nil)
require.NoError(t, err)
require.Equal(t, "GRANT USAGE ON *.* TO 'column'@'%' GRANT SELECT(a), INSERT(c), UPDATE(a, b) ON test.column_table TO 'column'@'%'", strings.Join(gs, " "))
require.Equal(t, "GRANT USAGE ON *.* TO 'column'@'%' GRANT SELECT(a), INSERT(c), UPDATE(a, b) ON `test`.`column_table` TO 'column'@'%'", strings.Join(gs, " "))
}

func TestDropTablePrivileges(t *testing.T) {
Expand Down Expand Up @@ -2315,26 +2315,26 @@ func TestGrantOptionAndRevoke(t *testing.T) {
Hostname: "localhost",
}, nil, nil, nil)

tk.MustQuery(`SHOW GRANTS FOR u1`).Check(testkit.Rows("GRANT SELECT ON *.* TO 'u1'@'%' WITH GRANT OPTION", "GRANT UPDATE,DELETE ON db.* TO 'u1'@'%'"))
tk.MustQuery(`SHOW GRANTS FOR u1`).Check(testkit.Rows("GRANT SELECT ON *.* TO 'u1'@'%' WITH GRANT OPTION", "GRANT UPDATE,DELETE ON `db`.* TO 'u1'@'%'"))

tk.MustExec("GRANT SELECT ON d1.* to u2")
tk.MustExec("GRANT SELECT ON d2.* to u2 WITH GRANT OPTION")
tk.MustExec("GRANT SELECT ON d3.* to u2")
tk.MustExec("GRANT SELECT ON d4.* to u2")
tk.MustExec("GRANT SELECT ON d5.* to u2")
tk.MustQuery(`SHOW GRANTS FOR u2;`).Sort().Check(testkit.Rows(
"GRANT SELECT ON d1.* TO 'u2'@'%'",
"GRANT SELECT ON d2.* TO 'u2'@'%' WITH GRANT OPTION",
"GRANT SELECT ON d3.* TO 'u2'@'%'",
"GRANT SELECT ON d4.* TO 'u2'@'%'",
"GRANT SELECT ON d5.* TO 'u2'@'%'",
"GRANT SELECT ON `d1`.* TO 'u2'@'%'",
"GRANT SELECT ON `d2`.* TO 'u2'@'%' WITH GRANT OPTION",
"GRANT SELECT ON `d3`.* TO 'u2'@'%'",
"GRANT SELECT ON `d4`.* TO 'u2'@'%'",
"GRANT SELECT ON `d5`.* TO 'u2'@'%'",
"GRANT USAGE ON *.* TO 'u2'@'%'",
))

tk.MustExec("grant all on hchwang.* to u3 with grant option")
tk.MustQuery(`SHOW GRANTS FOR u3;`).Check(testkit.Rows("GRANT USAGE ON *.* TO 'u3'@'%'", "GRANT ALL PRIVILEGES ON hchwang.* TO 'u3'@'%' WITH GRANT OPTION"))
tk.MustQuery(`SHOW GRANTS FOR u3;`).Check(testkit.Rows("GRANT USAGE ON *.* TO 'u3'@'%'", "GRANT ALL PRIVILEGES ON `hchwang`.* TO 'u3'@'%' WITH GRANT OPTION"))
tk.MustExec("revoke all on hchwang.* from u3")
tk.MustQuery(`SHOW GRANTS FOR u3;`).Check(testkit.Rows("GRANT USAGE ON *.* TO 'u3'@'%'", "GRANT USAGE ON hchwang.* TO 'u3'@'%' WITH GRANT OPTION"))
tk.MustQuery(`SHOW GRANTS FOR u3;`).Check(testkit.Rows("GRANT USAGE ON *.* TO 'u3'@'%'", "GRANT USAGE ON `hchwang`.* TO 'u3'@'%' WITH GRANT OPTION"))

// Same again but with column privileges.

Expand All @@ -2344,8 +2344,8 @@ func TestGrantOptionAndRevoke(t *testing.T) {
tk.MustExec("revoke all on test.testgrant from u3")
tk.MustQuery(`SHOW GRANTS FOR u3`).Sort().Check(testkit.Rows(
"GRANT USAGE ON *.* TO 'u3'@'%'",
"GRANT USAGE ON hchwang.* TO 'u3'@'%' WITH GRANT OPTION",
"GRANT USAGE ON test.testgrant TO 'u3'@'%' WITH GRANT OPTION",
"GRANT USAGE ON `hchwang`.* TO 'u3'@'%' WITH GRANT OPTION",
"GRANT USAGE ON `test`.`testgrant` TO 'u3'@'%' WITH GRANT OPTION",
))
}

Expand Down Expand Up @@ -2382,8 +2382,8 @@ func TestGrantReferences(t *testing.T) {
}, nil, nil, nil)
tk.MustQuery("SHOW GRANTS FOR referencesUser").Check(testkit.Rows(
`GRANT REFERENCES ON *.* TO 'referencesUser'@'%'`,
`GRANT REFERENCES ON reftestdb.* TO 'referencesUser'@'%'`,
`GRANT REFERENCES ON reftestdb.reftest TO 'referencesUser'@'%'`))
"GRANT REFERENCES ON `reftestdb`.* TO 'referencesUser'@'%'",
"GRANT REFERENCES ON `reftestdb`.`reftest` TO 'referencesUser'@'%'"))
tk.MustExec("DROP USER referencesUser")
tk.MustExec("DROP SCHEMA reftestdb")
}
Expand Down Expand Up @@ -2535,7 +2535,7 @@ func TestGrantLockTables(t *testing.T) {
}, nil, nil, nil)
tk.MustQuery("SHOW GRANTS FOR lock_tables_user").Check(testkit.Rows(
`GRANT LOCK TABLES ON *.* TO 'lock_tables_user'@'%'`,
`GRANT LOCK TABLES ON lock_tables_db.* TO 'lock_tables_user'@'%'`))
"GRANT LOCK TABLES ON `lock_tables_db`.* TO 'lock_tables_user'@'%'"))
tk.MustExec("DROP USER lock_tables_user")
tk.MustExec("DROP DATABASE lock_tables_db")
}
Expand Down Expand Up @@ -2576,16 +2576,16 @@ func TestShowGrantsForCurrentUserUsingRole(t *testing.T) {

tk.MustQuery("SHOW GRANTS FOR current_user() USING otherrole;").Check(testkit.Rows(
"GRANT USAGE ON *.* TO 'joe'@'%'",
"GRANT SELECT ON test.* TO 'joe'@'%'",
"GRANT UPDATE ON role.* TO 'joe'@'%'",
"GRANT SELECT,DELETE ON mysql.user TO 'joe'@'%'",
"GRANT SELECT ON `test`.* TO 'joe'@'%'",
"GRANT UPDATE ON `role`.* TO 'joe'@'%'",
"GRANT SELECT,DELETE ON `mysql`.`user` TO 'joe'@'%'",
"GRANT 'admins'@'%', 'engineering'@'%', 'otherrole'@'%' TO 'joe'@'%'",
))
tk.MustQuery("SHOW GRANTS FOR joe USING otherrole;").Check(testkit.Rows(
"GRANT USAGE ON *.* TO 'joe'@'%'",
"GRANT SELECT ON test.* TO 'joe'@'%'",
"GRANT UPDATE ON role.* TO 'joe'@'%'",
"GRANT SELECT,DELETE ON mysql.user TO 'joe'@'%'",
"GRANT SELECT ON `test`.* TO 'joe'@'%'",
"GRANT UPDATE ON `role`.* TO 'joe'@'%'",
"GRANT SELECT,DELETE ON `mysql`.`user` TO 'joe'@'%'",
"GRANT 'admins'@'%', 'engineering'@'%', 'otherrole'@'%' TO 'joe'@'%'",
))
}
Expand Down Expand Up @@ -2703,7 +2703,7 @@ func TestGrantCreateTmpTables(t *testing.T) {
}, nil, nil, nil)
tk.MustQuery("SHOW GRANTS FOR u1").Check(testkit.Rows(
`GRANT CREATE TEMPORARY TABLES ON *.* TO 'u1'@'%'`,
`GRANT CREATE TEMPORARY TABLES ON create_tmp_table_db.* TO 'u1'@'%'`))
"GRANT CREATE TEMPORARY TABLES ON `create_tmp_table_db`.* TO 'u1'@'%'"))
tk.MustExec("DROP USER u1")
tk.MustExec("DROP DATABASE create_tmp_table_db")
}
Expand Down Expand Up @@ -2899,7 +2899,7 @@ func TestGrantEvent(t *testing.T) {
}, nil, nil, nil)
tk.MustQuery("SHOW GRANTS FOR u1").Check(testkit.Rows(
`GRANT EVENT ON *.* TO 'u1'@'%'`,
`GRANT EVENT ON event_db.* TO 'u1'@'%'`))
"GRANT EVENT ON `event_db`.* TO 'u1'@'%'"))
tk.MustExec("DROP USER u1")
tk.MustExec("DROP DATABASE event_db")
}
Expand All @@ -2923,7 +2923,7 @@ func TestGrantRoutine(t *testing.T) {
}, nil, nil, nil)
tk.MustQuery("SHOW GRANTS FOR u1").Check(testkit.Rows(
`GRANT CREATE ROUTINE,ALTER ROUTINE ON *.* TO 'u1'@'%'`,
`GRANT CREATE ROUTINE,ALTER ROUTINE ON routine_db.* TO 'u1'@'%'`))
"GRANT CREATE ROUTINE,ALTER ROUTINE ON `routine_db`.* TO 'u1'@'%'"))
tk.MustExec("DROP USER u1")
tk.MustExec("DROP DATABASE routine_db")
}
Expand Down Expand Up @@ -3279,3 +3279,31 @@ func TestNilHandleInConnectionVerification(t *testing.T) {
tk := testkit.NewTestKit(t, store)
require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: `%`}, nil, nil, nil))
}

func testShowGrantsSQLMode(t *testing.T, tk *testkit.TestKit, expected []string) {
pc := privilege.GetPrivilegeManager(tk.Session())
gs, err := pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "show_sql_mode", Hostname: "localhost"}, nil)
require.NoError(t, err)
require.Len(t, gs, 2)
require.True(t, testutil.CompareUnorderedStringSlice(gs, expected), fmt.Sprintf("gs: %v, expected: %v", gs, expected))
}

func TestShowGrantsSQLMode(t *testing.T) {
store := createStoreAndPrepareDB(t)

tk := testkit.NewTestKit(t, store)
ctx, _ := tk.Session().(sessionctx.Context)
tk.MustExec(`CREATE USER 'show_sql_mode'@'localhost' identified by '123';`)
tk.MustExec(`GRANT Select ON test.* TO 'show_sql_mode'@'localhost';`)

testShowGrantsSQLMode(t, tk, []string{
"GRANT USAGE ON *.* TO 'show_sql_mode'@'localhost'",
"GRANT SELECT ON `test`.* TO 'show_sql_mode'@'localhost'",
})

ctx.GetSessionVars().SQLMode = mysql.SetSQLMode(ctx.GetSessionVars().SQLMode, mysql.ModeANSIQuotes)
testShowGrantsSQLMode(t, tk, []string{
"GRANT USAGE ON *.* TO 'show_sql_mode'@'localhost'",
"GRANT SELECT ON \"test\".* TO 'show_sql_mode'@'localhost'",
})
}
Loading

0 comments on commit 6271d1c

Please sign in to comment.