-
Notifications
You must be signed in to change notification settings - Fork 5.9k
/
privileges.go
141 lines (117 loc) · 3.79 KB
/
privileges.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package privileges
import (
"strings"
log "github.com/Sirupsen/logrus"
"github.com/pingcap/tidb/context"
"github.com/pingcap/tidb/mysql"
"github.com/pingcap/tidb/privilege"
"github.com/pingcap/tidb/terror"
"github.com/pingcap/tidb/util/auth"
"github.com/pingcap/tidb/util/types"
)
// Enable enables the new privilege check feature.
var Enable = true
// SkipWithGrant causes the server to start without using the privilege system at all.
var SkipWithGrant = false
// privilege error codes.
const (
codeInvalidPrivilegeType terror.ErrCode = 1
codeInvalidUserNameFormat = 2
)
var (
errInvalidPrivilegeType = terror.ClassPrivilege.New(codeInvalidPrivilegeType, "unknown privilege type")
errInvalidUserNameFormat = terror.ClassPrivilege.New(codeInvalidUserNameFormat, "wrong username format")
)
var _ privilege.Manager = (*UserPrivileges)(nil)
// UserPrivileges implements privilege.Manager interface.
// This is used to check privilege for the current user.
type UserPrivileges struct {
user string
host string
*Handle
}
// RequestVerification implements the Manager interface.
func (p *UserPrivileges) RequestVerification(db, table, column string, priv mysql.PrivilegeType) bool {
if !Enable || SkipWithGrant {
return true
}
if p.user == "" && p.host == "" {
return true
}
// Skip check for INFORMATION_SCHEMA database.
// See https://dev.mysql.com/doc/refman/5.7/en/information-schema.html
if strings.EqualFold(db, "INFORMATION_SCHEMA") {
return true
}
mysqlPriv := p.Handle.Get()
return mysqlPriv.RequestVerification(p.user, p.host, db, table, column, priv)
}
// ConnectionVerification implements the Manager interface.
func (p *UserPrivileges) ConnectionVerification(user, host string, authentication, salt []byte) bool {
if SkipWithGrant {
p.user = user
p.host = host
return true
}
mysqlPriv := p.Handle.Get()
record := mysqlPriv.connectionVerification(user, host)
if record == nil {
log.Errorf("Get user privilege record fail: user %v, host %v", user, host)
return false
}
pwd := record.Password
if len(pwd) != 0 && len(pwd) != mysql.PWDHashLen+1 {
log.Errorf("User [%s] password from SystemDB not like a sha1sum", user)
return false
}
// empty password
if len(pwd) == 0 && len(authentication) == 0 {
p.user = user
p.host = host
return true
}
if len(pwd) == 0 || len(authentication) == 0 {
return false
}
hpwd, err := auth.DecodePassword(pwd)
if err != nil {
log.Errorf("Decode password string error %v", err)
return false
}
if !auth.CheckScrambledPassword(salt, hpwd, authentication) {
return false
}
p.user = user
p.host = host
return true
}
// DBIsVisible implements the Manager interface.
func (p *UserPrivileges) DBIsVisible(db string) bool {
if !Enable || SkipWithGrant {
return true
}
mysqlPriv := p.Handle.Get()
return mysqlPriv.DBIsVisible(p.user, p.host, db)
}
// UserPrivilegesTable implements the Manager interface.
func (p *UserPrivileges) UserPrivilegesTable() [][]types.Datum {
mysqlPriv := p.Handle.Get()
return mysqlPriv.UserPrivilegesTable()
}
// ShowGrants implements privilege.Manager ShowGrants interface.
func (p *UserPrivileges) ShowGrants(ctx context.Context, user *auth.UserIdentity) ([]string, error) {
mysqlPrivilege := p.Handle.Get()
return mysqlPrivilege.showGrants(user.Username, user.Hostname), nil
}