Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

executor: Escape object in show grants output | tidb-test=pr/2217 #46976

Merged
merged 10 commits into from
Sep 20, 2023
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