Skip to content

Commit d644619

Browse files
authored
Merge pull request #2786 from dolthub/fulghum-588631ab
[auto-bump] [no-release-notes] dependency by fulghum
2 parents d3cdbb6 + e99d9e2 commit d644619

File tree

14 files changed

+185
-51
lines changed

14 files changed

+185
-51
lines changed

enginetest/queries/priv_auth_queries.go

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -692,15 +692,55 @@ var UserPrivTests = []UserPrivilegeTest{
692692
},
693693
},
694694
{
695-
Query: "SELECT Host, User FROM mysql.user;",
695+
Query: "SELECT Host, User, Plugin, length(authentication_string) > 0 FROM mysql.user order by User;",
696696
Expected: []sql.Row{
697-
{"localhost", "root"},
698-
{"localhost", "testuser2"},
699-
{"127.0.0.1", "testuser"},
697+
{"localhost", "root", "mysql_native_password", false},
698+
{"127.0.0.1", "testuser", "mysql_native_password", false},
699+
// testuser2 was inserted directly into the table, so it uses the column default
700+
// from the plugin field – caching_sha2_password
701+
{"localhost", "testuser2", "caching_sha2_password", false},
700702
},
701703
},
702704
},
703705
},
706+
{
707+
Name: "User creation with auth plugin specified: mysql_native_password",
708+
SetUpScript: []string{
709+
"CREATE USER testuser1@`127.0.0.1` identified with mysql_native_password by 'pass1';",
710+
"CREATE USER testuser2@`127.0.0.1` identified with 'mysql_native_password';",
711+
},
712+
Assertions: []UserPrivilegeTestAssertion{
713+
{
714+
Query: "select user, host, plugin, authentication_string from mysql.user where user='testuser1';",
715+
Expected: []sql.Row{{"testuser1", "127.0.0.1", "mysql_native_password", "*22A99BA288DB55E8E230679259740873101CD636"}},
716+
},
717+
{
718+
Query: "select user, host, plugin, authentication_string from mysql.user where user='testuser2';",
719+
Expected: []sql.Row{{"testuser2", "127.0.0.1", "mysql_native_password", ""}},
720+
},
721+
},
722+
},
723+
{
724+
Name: "User creation with auth plugin specified: caching_sha2_password",
725+
SetUpScript: []string{
726+
"CREATE USER testuser1@`127.0.0.1` identified with caching_sha2_password by 'pass1';",
727+
"CREATE USER testuser2@`127.0.0.1` identified with 'caching_sha2_password';",
728+
},
729+
Assertions: []UserPrivilegeTestAssertion{
730+
{
731+
// caching_sha2_password auth uses a random salt to create the authentication
732+
// string. Since it's not a consistent value during each test run, we just sanity
733+
// check the first bytes of metadata (digest type, iterations) in the auth string.
734+
Query: "select user, host, plugin, authentication_string like '$A$005$%' from mysql.user where user='testuser1';",
735+
Expected: []sql.Row{{"testuser1", "127.0.0.1", "caching_sha2_password", true}},
736+
},
737+
{
738+
Query: "select user, host, plugin, authentication_string from mysql.user where user='testuser2';",
739+
Expected: []sql.Row{{"testuser2", "127.0.0.1", "caching_sha2_password", ""}},
740+
},
741+
},
742+
},
743+
704744
{
705745
Name: "Dynamic privilege support",
706746
SetUpScript: []string{

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ require (
66
github.com/dolthub/go-icu-regex v0.0.0-20240916130659-0118adc6b662
77
github.com/dolthub/jsonpath v0.0.2-0.20240227200619-19675ab05c71
88
github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81
9-
github.com/dolthub/vitess v0.0.0-20241206185536-814752c66695
9+
github.com/dolthub/vitess v0.0.0-20241209181212-588631aba4be
1010
github.com/go-kit/kit v0.10.0
1111
github.com/go-sql-driver/mysql v1.7.2-0.20231213112541-0004702b931d
1212
github.com/gocraft/dbr/v2 v2.7.2

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81 h1:7/v8q9X
6060
github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81/go.mod h1:siLfyv2c92W1eN/R4QqG/+RjjX5W2+gCTRjZxBjI3TY=
6161
github.com/dolthub/vitess v0.0.0-20241206185536-814752c66695 h1:jqTM+/S/LKYdsdretQMalu7dhHupuweSPiPNC2Jpoiw=
6262
github.com/dolthub/vitess v0.0.0-20241206185536-814752c66695/go.mod h1:1gQZs/byeHLMSul3Lvl3MzioMtOW1je79QYGyi2fd70=
63+
github.com/dolthub/vitess v0.0.0-20241209181212-588631aba4be h1:YF+vUXEAMqai036iZPJS2JRKd3pXcCQ1TYcLWBR4boo=
64+
github.com/dolthub/vitess v0.0.0-20241209181212-588631aba4be/go.mod h1:1gQZs/byeHLMSul3Lvl3MzioMtOW1je79QYGyi2fd70=
6365
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
6466
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
6567
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=

sql/mysql_db/auth.go

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ import (
2727
"github.com/dolthub/go-mysql-server/sql"
2828
)
2929

30+
// DefaultAuthMethod specifies the MySQL auth protocol (e.g. mysql_native_password,
31+
// caching_sha2_password) that is used by default. When the auth server advertises
32+
// what auth protocol it prefers, as part of the auth handshake, it is controlled
33+
// by this constant. When a new user is created, if no auth plugin is specified, this
34+
// auth method will be used.
35+
const DefaultAuthMethod = mysql.MysqlNativePassword
36+
3037
// authServer implements the mysql.AuthServer interface. It exposes configured AuthMethod implementations
3138
// that the auth framework in Vitess uses to negotiate authentication with a client. By default, authServer
3239
// configures support for the mysql_native_password auth plugin, as well as an extensible auth method, built
@@ -42,10 +49,10 @@ var _ mysql.AuthServer = (*authServer)(nil)
4249
// mysql_native_password support, as well as an extensible auth method, built on the mysql_clear_password auth
4350
// method, that allows integrators to extend authentication to allow additional schemes.
4451
func newAuthServer(db *MySQLDb) *authServer {
45-
// The native password auth method allows auth over the mysql_native_password protocol
52+
// mysql_native_password auth support
4653
nativePasswordAuthMethod := mysql.NewMysqlNativeAuthMethod(
4754
&nativePasswordHashStorage{db: db},
48-
&nativePasswordUserValidator{db: db})
55+
newUserValidator(db, mysql.MysqlNativePassword))
4956

5057
// TODO: Add CachingSha2Password AuthMethod
5158

@@ -67,7 +74,7 @@ func (as *authServer) AuthMethods() []mysql.AuthMethod {
6774

6875
// DefaultAuthMethodDescription implements the mysql.AuthServer interface.
6976
func (db *authServer) DefaultAuthMethodDescription() mysql.AuthMethodDescription {
70-
return mysql.MysqlNativePassword
77+
return DefaultAuthMethod
7178
}
7279

7380
// extendedAuthPlainTextStorage implements the mysql.PlainTextStorage interface and plugs into
@@ -205,8 +212,8 @@ func (nphs *nativePasswordHashStorage) UserEntryWithHash(_ []*x509.Certificate,
205212
if userEntry == nil || userEntry.Locked {
206213
return nil, mysql.NewSQLError(mysql.ERAccessDeniedError, mysql.SSAccessDeniedError, "Access denied for user '%v'", user)
207214
}
208-
if len(userEntry.Password) > 0 {
209-
if !validateMysqlNativePassword(authResponse, salt, userEntry.Password) {
215+
if len(userEntry.AuthString) > 0 {
216+
if !validateMysqlNativePassword(authResponse, salt, userEntry.AuthString) {
210217
return nil, mysql.NewSQLError(mysql.ERAccessDeniedError, mysql.SSAccessDeniedError, "Access denied for user '%v'", user)
211218
}
212219
} else if len(authResponse) > 0 {
@@ -218,18 +225,32 @@ func (nphs *nativePasswordHashStorage) UserEntryWithHash(_ []*x509.Certificate,
218225
return sql.MysqlConnectionUser{User: userEntry.User, Host: userEntry.Host}, nil
219226
}
220227

221-
// nativePasswordUserValidator implements the mysql.UserValidator interface and plugs into the mysql_native_password
222-
// auth method in Vitess. This implementation is called by the native password auth method to determine if a specific
223-
// user and remote address can connect to this server via the mysql_native_password auth protocol.
224-
type nativePasswordUserValidator struct {
228+
// userValidator implements the mysql.UserValidator interface. It looks up a user and host from the
229+
// associated mysql database (|db|) and validates that a user entry exists and that it is configured
230+
// for the specified authentication plugin (|authMethod|).
231+
type userValidator struct {
232+
// db is the mysql database that contains user information
225233
db *MySQLDb
234+
235+
// authMethod is the name of the auth plugin for which this validator will
236+
// validate users.
237+
authMethod mysql.AuthMethodDescription
226238
}
227239

228-
var _ mysql.UserValidator = (*nativePasswordUserValidator)(nil)
240+
var _ mysql.UserValidator = (*userValidator)(nil)
241+
242+
// newUserValidator creates a new userValidator instance, configured to use |db| to look up user
243+
// entries and validate that they have the specified auth plugin (|authMethod|) configured.
244+
func newUserValidator(db *MySQLDb, authMethod mysql.AuthMethodDescription) *userValidator {
245+
return &userValidator{
246+
db: db,
247+
authMethod: authMethod,
248+
}
249+
}
229250

230251
// HandleUser implements the mysql.UserValidator interface and verifies if the mysql_native_password auth method
231252
// can be used for the specified |user| at the specified |remoteAddr|.
232-
func (uv *nativePasswordUserValidator) HandleUser(user string, remoteAddr net.Addr) bool {
253+
func (uv *userValidator) HandleUser(user string, remoteAddr net.Addr) bool {
233254
// If the mysql database is not enabled, then we don't have user information, so
234255
// go ahead and return true without trying to look up the user in the db.
235256
if !uv.db.Enabled() {
@@ -251,7 +272,7 @@ func (uv *nativePasswordUserValidator) HandleUser(user string, remoteAddr net.Ad
251272
}
252273
userEntry := db.GetUser(rd, user, host, false)
253274

254-
return userEntry != nil && (userEntry.Plugin == "" || userEntry.Plugin == string(mysql.MysqlNativePassword))
275+
return userEntry != nil && userEntry.Plugin == string(uv.authMethod)
255276
}
256277

257278
// extractHostAddress extracts the host address from |addr|, checking to see if it is a unix socket, and if

sql/mysql_db/mysql_db.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -780,8 +780,8 @@ func (db *MySQLDb) ValidateHash(salt []byte, user string, authResponse []byte, a
780780
if userEntry == nil || userEntry.Locked {
781781
return nil, mysql.NewSQLError(mysql.ERAccessDeniedError, mysql.SSAccessDeniedError, "Access denied for user '%v'", user)
782782
}
783-
if len(userEntry.Password) > 0 {
784-
if !validateMysqlNativePassword(authResponse, salt, userEntry.Password) {
783+
if len(userEntry.AuthString) > 0 {
784+
if !validateMysqlNativePassword(authResponse, salt, userEntry.AuthString) {
785785
return nil, mysql.NewSQLError(mysql.ERAccessDeniedError, mysql.SSAccessDeniedError, "Access denied for user '%v'", user)
786786
}
787787
} else if len(authResponse) > 0 { // password is nil or empty, therefore no password is set

sql/mysql_db/mysql_db_load.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ func LoadUser(serialUser *serial.User) *User {
132132
Host: string(serialUser.Host()),
133133
PrivilegeSet: *privilegeSet,
134134
Plugin: string(serialUser.Plugin()),
135-
Password: string(serialUser.Password()),
135+
AuthString: string(serialUser.Password()),
136136
PasswordLastChanged: time.Unix(serialUser.PasswordLastChanged(), 0),
137137
Locked: serialUser.Locked(),
138138
Attributes: attributes,

sql/mysql_db/mysql_db_serialize.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ func serializeUser(b *flatbuffers.Builder, users []*User) flatbuffers.UOffsetT {
169169
host := b.CreateString(user.Host)
170170
privilegeSet := serializePrivilegeSet(b, &user.PrivilegeSet)
171171
plugin := b.CreateString(user.Plugin)
172-
password := b.CreateString(user.Password)
172+
authString := b.CreateString(user.AuthString)
173173
attributes := serializeAttributes(b, user.Attributes)
174174
identity := b.CreateString(user.Identity)
175175

@@ -178,7 +178,7 @@ func serializeUser(b *flatbuffers.Builder, users []*User) flatbuffers.UOffsetT {
178178
serial.UserAddHost(b, host)
179179
serial.UserAddPrivilegeSet(b, privilegeSet)
180180
serial.UserAddPlugin(b, plugin)
181-
serial.UserAddPassword(b, password)
181+
serial.UserAddPassword(b, authString)
182182
serial.UserAddPasswordLastChanged(b, user.PasswordLastChanged.Unix())
183183
serial.UserAddLocked(b, user.Locked)
184184
serial.UserAddAttributes(b, attributes)

sql/mysql_db/user.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ type User struct {
3030
Host string
3131
PrivilegeSet PrivilegeSet
3232
Plugin string
33-
Password string
33+
AuthString string
3434
PasswordLastChanged time.Time
3535
Locked bool
3636
Attributes *string
@@ -56,7 +56,7 @@ func UserToRow(ctx *sql.Context, u *User) (sql.Row, error) {
5656
row[userTblColIndex_User] = u.User
5757
row[userTblColIndex_Host] = u.Host
5858
row[userTblColIndex_plugin] = u.Plugin
59-
row[userTblColIndex_authentication_string] = u.Password
59+
row[userTblColIndex_authentication_string] = u.AuthString
6060
row[userTblColIndex_password_last_changed] = u.PasswordLastChanged
6161
row[userTblColIndex_identity] = u.Identity
6262
if u.Locked {
@@ -87,7 +87,7 @@ func UserFromRow(ctx *sql.Context, row sql.Row) (*User, error) {
8787
Host: row[userTblColIndex_Host].(string),
8888
PrivilegeSet: UserRowToPrivSet(ctx, row),
8989
Plugin: row[userTblColIndex_plugin].(string),
90-
Password: row[userTblColIndex_authentication_string].(string),
90+
AuthString: row[userTblColIndex_authentication_string].(string),
9191
PasswordLastChanged: passwordLastChanged,
9292
Locked: row[userTblColIndex_account_locked].(uint16) == 2,
9393
Attributes: attributes,
@@ -117,7 +117,7 @@ func UserEquals(left, right *User) bool {
117117
if left.User != right.User ||
118118
left.Host != right.Host ||
119119
left.Plugin != right.Plugin ||
120-
left.Password != right.Password ||
120+
left.AuthString != right.AuthString ||
121121
left.Identity != right.Identity ||
122122
!left.PasswordLastChanged.Equal(right.PasswordLastChanged) ||
123123
left.Locked != right.Locked ||

sql/mysql_db/user_table.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,13 +215,13 @@ func init() {
215215
}
216216
}
217217

218-
func addSuperUser(ed *Editor, username string, host string, password string) {
218+
func addSuperUser(ed *Editor, username string, host string, authString string) {
219219
ed.PutUser(&User{
220220
User: username,
221221
Host: host,
222222
PrivilegeSet: NewPrivilegeSetWithAllPrivileges(),
223223
Plugin: "mysql_native_password",
224-
Password: password,
224+
AuthString: authString,
225225
PasswordLastChanged: time.Unix(1, 0).UTC(),
226226
Locked: false,
227227
Attributes: nil,

sql/mysql_db/user_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func TestUserJson(t *testing.T) {
3434
Host: "localhost",
3535
PrivilegeSet: NewPrivilegeSet(),
3636
Plugin: "mysql_native_password",
37-
Password: "*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19",
37+
AuthString: "*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19",
3838
PasswordLastChanged: time.Unix(184301, 0),
3939
Locked: false,
4040
Attributes: nil,

0 commit comments

Comments
 (0)