Skip to content

Commit

Permalink
Extend TestHandleAuthPlugin
Browse files Browse the repository at this point in the history
  • Loading branch information
dveeden committed Nov 23, 2021
1 parent cfd2d2c commit 0304b51
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 7 deletions.
18 changes: 13 additions & 5 deletions server/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ func (cc *clientConn) String() string {
// https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchRequest
// https://bugs.mysql.com/bug.php?id=93044
func (cc *clientConn) authSwitchRequest(ctx context.Context, plugin string) ([]byte, error) {
failpoint.Inject("FakeAuthSwitch", func() {
failpoint.Return([]byte(plugin), nil)
})
enclen := 1 + len(plugin) + 1 + len(cc.salt) + 1
data := cc.alloc.AllocWithLen(4, enclen)
data = append(data, mysql.AuthSwitchRequest) // switch request
Expand Down Expand Up @@ -854,6 +857,9 @@ func (cc *clientConn) checkAuthPlugin(ctx context.Context, resp *handshakeRespon
return nil, err
}
userplugin, err := cc.ctx.AuthPluginForUser(&auth.UserIdentity{Username: cc.user, Hostname: host})
failpoint.Inject("FakeUser", func(val failpoint.Value) {
userplugin = val.(string)
})
if err != nil {
// This happens if the account doesn't exist
logutil.Logger(ctx).Warn("Failed to get authentication method for user",
Expand All @@ -872,12 +878,14 @@ func (cc *clientConn) checkAuthPlugin(ctx context.Context, resp *handshakeRespon
// This happens if the account doesn't exist or if the account doesn't have
// a password set.
if resp.AuthPlugin != mysql.AuthNativePassword {
resp.AuthPlugin = mysql.AuthNativePassword
authData, err := cc.authSwitchRequest(ctx, mysql.AuthNativePassword)
if err != nil {
return nil, err
if resp.Capability&mysql.ClientPluginAuth > 0 {
resp.AuthPlugin = mysql.AuthNativePassword
authData, err := cc.authSwitchRequest(ctx, mysql.AuthNativePassword)
if err != nil {
return nil, err
}
return authData, nil
}
return authData, nil
}
return nil, nil
}
Expand Down
173 changes: 171 additions & 2 deletions server/conn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -922,7 +922,9 @@ func TestHandleAuthPlugin(t *testing.T) {
drv := NewTiDBDriver(store)
srv, err := NewServer(cfg, drv)
require.NoError(t, err)
ctx := context.Background()

// 5.7 or newer client trying to authenticate with mysql_native_password
cc := &clientConn{
connectionID: 1,
alloc: arena.NewAllocator(1024),
Expand All @@ -934,17 +936,184 @@ func TestHandleAuthPlugin(t *testing.T) {
},
server: srv,
}
ctx := context.Background()
resp := handshakeResponse41{
Capability: mysql.ClientProtocol41 | mysql.ClientPluginAuth,
AuthPlugin: mysql.AuthNativePassword,
}
err = cc.handleAuthPlugin(ctx, &resp)
require.NoError(t, err)

resp.Capability = mysql.ClientProtocol41
// 8.0 or newer client trying to authenticate with caching_sha2_password
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/server/FakeAuthSwitch", "return(1)"))
cc = &clientConn{
connectionID: 1,
alloc: arena.NewAllocator(1024),
chunkAlloc: chunk.NewAllocator(),
collation: mysql.DefaultCollationID,
peerHost: "localhost",
pkt: &packetIO{
bufWriter: bufio.NewWriter(bytes.NewBuffer(nil)),
},
server: srv,
}
resp = handshakeResponse41{
Capability: mysql.ClientProtocol41 | mysql.ClientPluginAuth,
AuthPlugin: mysql.AuthCachingSha2Password,
}
err = cc.handleAuthPlugin(ctx, &resp)
require.NoError(t, err)
require.Equal(t, resp.Auth, []byte(mysql.AuthNativePassword))
require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/server/FakeAuthSwitch"))

// MySQL 5.1 or older client, without authplugin support
cc = &clientConn{
connectionID: 1,
alloc: arena.NewAllocator(1024),
chunkAlloc: chunk.NewAllocator(),
collation: mysql.DefaultCollationID,
peerHost: "localhost",
pkt: &packetIO{
bufWriter: bufio.NewWriter(bytes.NewBuffer(nil)),
},
server: srv,
}
resp = handshakeResponse41{
Capability: mysql.ClientProtocol41,
}
err = cc.handleAuthPlugin(ctx, &resp)
require.NoError(t, err)

// === Target account has mysql_native_password ===
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/server/FakeUser", "return(\"mysql_native_password\")"))

// 5.7 or newer client trying to authenticate with mysql_native_password
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/server/FakeAuthSwitch", "return(1)"))
cc = &clientConn{
connectionID: 1,
alloc: arena.NewAllocator(1024),
chunkAlloc: chunk.NewAllocator(),
collation: mysql.DefaultCollationID,
peerHost: "localhost",
pkt: &packetIO{
bufWriter: bufio.NewWriter(bytes.NewBuffer(nil)),
},
server: srv,
}
resp = handshakeResponse41{
Capability: mysql.ClientProtocol41 | mysql.ClientPluginAuth,
AuthPlugin: mysql.AuthNativePassword,
}
err = cc.handleAuthPlugin(ctx, &resp)
require.NoError(t, err)
require.Equal(t, resp.Auth, []byte(mysql.AuthNativePassword))
require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/server/FakeAuthSwitch"))

// 8.0 or newer client trying to authenticate with caching_sha2_password
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/server/FakeAuthSwitch", "return(1)"))
cc = &clientConn{
connectionID: 1,
alloc: arena.NewAllocator(1024),
chunkAlloc: chunk.NewAllocator(),
collation: mysql.DefaultCollationID,
peerHost: "localhost",
pkt: &packetIO{
bufWriter: bufio.NewWriter(bytes.NewBuffer(nil)),
},
server: srv,
}
resp = handshakeResponse41{
Capability: mysql.ClientProtocol41 | mysql.ClientPluginAuth,
AuthPlugin: mysql.AuthCachingSha2Password,
}
err = cc.handleAuthPlugin(ctx, &resp)
require.NoError(t, err)
require.Equal(t, resp.Auth, []byte(mysql.AuthNativePassword))
require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/server/FakeAuthSwitch"))

// MySQL 5.1 or older client, without authplugin support
cc = &clientConn{
connectionID: 1,
alloc: arena.NewAllocator(1024),
chunkAlloc: chunk.NewAllocator(),
collation: mysql.DefaultCollationID,
peerHost: "localhost",
pkt: &packetIO{
bufWriter: bufio.NewWriter(bytes.NewBuffer(nil)),
},
server: srv,
}
resp = handshakeResponse41{
Capability: mysql.ClientProtocol41,
}
err = cc.handleAuthPlugin(ctx, &resp)
require.NoError(t, err)
require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/server/FakeUser"))

// === Target account has caching_sha2_password ===
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/server/FakeUser", "return(\"caching_sha2_password\")"))

// 5.7 or newer client trying to authenticate with mysql_native_password
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/server/FakeAuthSwitch", "return(1)"))
cc = &clientConn{
connectionID: 1,
alloc: arena.NewAllocator(1024),
chunkAlloc: chunk.NewAllocator(),
collation: mysql.DefaultCollationID,
peerHost: "localhost",
pkt: &packetIO{
bufWriter: bufio.NewWriter(bytes.NewBuffer(nil)),
},
server: srv,
}
resp = handshakeResponse41{
Capability: mysql.ClientProtocol41 | mysql.ClientPluginAuth,
AuthPlugin: mysql.AuthNativePassword,
}
err = cc.handleAuthPlugin(ctx, &resp)
require.NoError(t, err)
require.Equal(t, resp.Auth, []byte(mysql.AuthCachingSha2Password))
require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/server/FakeAuthSwitch"))

// 8.0 or newer client trying to authenticate with caching_sha2_password
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/server/FakeAuthSwitch", "return(1)"))
cc = &clientConn{
connectionID: 1,
alloc: arena.NewAllocator(1024),
chunkAlloc: chunk.NewAllocator(),
collation: mysql.DefaultCollationID,
peerHost: "localhost",
pkt: &packetIO{
bufWriter: bufio.NewWriter(bytes.NewBuffer(nil)),
},
server: srv,
}
resp = handshakeResponse41{
Capability: mysql.ClientProtocol41 | mysql.ClientPluginAuth,
AuthPlugin: mysql.AuthCachingSha2Password,
}
err = cc.handleAuthPlugin(ctx, &resp)
require.NoError(t, err)
require.Equal(t, resp.Auth, []byte(mysql.AuthCachingSha2Password))
require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/server/FakeAuthSwitch"))

// MySQL 5.1 or older client, without authplugin support
cc = &clientConn{
connectionID: 1,
alloc: arena.NewAllocator(1024),
chunkAlloc: chunk.NewAllocator(),
collation: mysql.DefaultCollationID,
peerHost: "localhost",
pkt: &packetIO{
bufWriter: bufio.NewWriter(bytes.NewBuffer(nil)),
},
server: srv,
}
resp = handshakeResponse41{
Capability: mysql.ClientProtocol41,
}
err = cc.handleAuthPlugin(ctx, &resp)
require.Error(t, err)
require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/server/FakeUser"))
}

func TestAuthPlugin2(t *testing.T) {
Expand Down

0 comments on commit 0304b51

Please sign in to comment.