Skip to content

Commit f972a49

Browse files
committed
added support for closing an authPlugin for plugins whose resources need to be cleaned up.
1 parent e273589 commit f972a49

File tree

3 files changed

+25
-10
lines changed

3 files changed

+25
-10
lines changed

auth.go

+15-5
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ type AuthPlugin interface {
3636
// Next takes a server's challenge and returns
3737
// the bytes to send back or an error.
3838
Next(challenge []byte) ([]byte, error)
39+
40+
// Close cleans up the resources of the plugin.
41+
Close()
3942
}
4043

4144
type clearTextPlugin struct {
@@ -51,6 +54,8 @@ func (p *clearTextPlugin) Next(challenge []byte) ([]byte, error) {
5154
return append([]byte(p.cfg.Passwd), 0), nil
5255
}
5356

57+
func (p *clearTextPlugin) Close() {}
58+
5459
type nativePasswordPlugin struct {
5560
cfg *Config
5661
}
@@ -64,6 +69,8 @@ func (p *nativePasswordPlugin) Next(challenge []byte) ([]byte, error) {
6469
return scramblePassword(challenge, []byte(p.cfg.Passwd)), nil
6570
}
6671

72+
func (p *nativePasswordPlugin) Close() {}
73+
6774
type oldPasswordPlugin struct {
6875
cfg *Config
6976
}
@@ -77,7 +84,9 @@ func (p *oldPasswordPlugin) Next(challenge []byte) ([]byte, error) {
7784
return append(scrambleOldPassword(challenge, []byte(p.cfg.Passwd)), 0), nil
7885
}
7986

80-
func handleAuthResult(mc *mysqlConn, plugin AuthPlugin, oldCipher []byte) error {
87+
func (p *oldPasswordPlugin) Close() {}
88+
89+
func handleAuthResult(mc *mysqlConn, oldCipher []byte) error {
8190
data, err := mc.readPacket()
8291
if err != nil {
8392
return err
@@ -91,11 +100,12 @@ func handleAuthResult(mc *mysqlConn, plugin AuthPlugin, oldCipher []byte) error
91100
return mc.handleOkPacket(data)
92101

93102
case iEOF: // auth switch
103+
mc.authPlugin.Close()
94104
if len(data) > 1 {
95105
pluginEndIndex := bytes.IndexByte(data, 0x00)
96106
pluginName := string(data[1:pluginEndIndex])
97107
if apf, ok := authPluginFactories[pluginName]; ok {
98-
plugin = apf(mc.cfg)
108+
mc.authPlugin = apf(mc.cfg)
99109
} else {
100110
return ErrUnknownPlugin
101111
}
@@ -105,7 +115,7 @@ func handleAuthResult(mc *mysqlConn, plugin AuthPlugin, oldCipher []byte) error
105115
}
106116
} else {
107117
// https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::OldAuthSwitchRequest
108-
plugin = authPluginFactories[mysqlOldPassword](mc.cfg)
118+
mc.authPlugin = authPluginFactories[mysqlOldPassword](mc.cfg)
109119
authData = oldCipher
110120
}
111121
case iAuthContinue:
@@ -115,7 +125,7 @@ func handleAuthResult(mc *mysqlConn, plugin AuthPlugin, oldCipher []byte) error
115125
return mc.handleErrorPacket(data)
116126
}
117127

118-
authData, err = plugin.Next(authData)
128+
authData, err = mc.authPlugin.Next(authData)
119129
if err != nil {
120130
return err
121131
}
@@ -125,5 +135,5 @@ func handleAuthResult(mc *mysqlConn, plugin AuthPlugin, oldCipher []byte) error
125135
return err
126136
}
127137

128-
return handleAuthResult(mc, plugin, authData)
138+
return handleAuthResult(mc, authData)
129139
}

connection.go

+5
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type mysqlConn struct {
3030
sequence uint8
3131
parseTime bool
3232
strict bool
33+
authPlugin AuthPlugin
3334
}
3435

3536
// Handles parameters set in DSN after the connection is established
@@ -92,6 +93,10 @@ func (mc *mysqlConn) Close() (err error) {
9293
// closed the network connection.
9394
func (mc *mysqlConn) cleanup() {
9495
// Makes cleanup idempotent
96+
if mc.authPlugin != nil {
97+
mc.authPlugin.Close()
98+
mc.authPlugin = nil
99+
}
95100
if mc.netConn != nil {
96101
if err := mc.netConn.Close(); err != nil {
97102
errLog.Print(err)

driver.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -106,18 +106,18 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
106106
authPluginName = defaultAuthPluginName
107107
}
108108

109-
var authPlugin AuthPlugin
110109
if apf, ok := authPluginFactories[authPluginName]; ok {
111-
authPlugin = apf(mc.cfg)
112-
authData, err = authPlugin.Next(authData)
110+
mc.authPlugin = apf(mc.cfg)
111+
authData, err = mc.authPlugin.Next(authData)
113112
if err != nil {
113+
mc.cleanup()
114114
return nil, err
115115
}
116116
} else {
117117
// we'll tell the server in response that we are switching to our
118118
// default plugin because we didn't recognize the one they sent us.
119119
authPluginName = defaultAuthPluginName
120-
authPlugin = authPluginFactories[authPluginName](mc.cfg)
120+
mc.authPlugin = authPluginFactories[authPluginName](mc.cfg)
121121

122122
// zero-out the authData because the current authData was for
123123
// a plugin we don't know about.
@@ -131,7 +131,7 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
131131
}
132132

133133
// Handle response to auth packet, switch methods if possible
134-
if err = handleAuthResult(mc, authPlugin, oldCipher); err != nil {
134+
if err = handleAuthResult(mc, oldCipher); err != nil {
135135
// Authentication failed and MySQL has already closed the connection
136136
// (https://dev.mysql.com/doc/internals/en/authentication-fails.html).
137137
// Do not send COM_QUIT, just cleanup and return the error.

0 commit comments

Comments
 (0)