@@ -154,6 +154,22 @@ func scrambleSHA256Password(scramble []byte, password string) []byte {
154
154
return message1
155
155
}
156
156
157
+ func (mc * mysqlConn ) sendEncryptedPassword (seed []byte , pub * rsa.PublicKey ) error {
158
+ plain := make ([]byte , len (mc .cfg .Passwd )+ 1 )
159
+ copy (plain , mc .cfg .Passwd )
160
+ for i := range plain {
161
+ j := i % len (seed )
162
+ plain [i ] ^= seed [j ]
163
+ }
164
+ sha1 := sha1 .New ()
165
+ enc , err := rsa .EncryptOAEP (sha1 , rand .Reader , pub , plain , nil )
166
+ if err != nil {
167
+ return err
168
+ }
169
+
170
+ return mc .writeAuthSwitchPacket (enc , false )
171
+ }
172
+
157
173
func (mc * mysqlConn ) auth (authData []byte , plugin string ) ([]byte , bool , error ) {
158
174
switch plugin {
159
175
case "caching_sha2_password" :
@@ -187,6 +203,18 @@ func (mc *mysqlConn) auth(authData []byte, plugin string) ([]byte, bool, error)
187
203
authResp := scramblePassword (authData [:20 ], mc .cfg .Passwd )
188
204
return authResp , false , nil
189
205
206
+ case "sha256_password" :
207
+ if len (mc .cfg .Passwd ) == 0 {
208
+ return nil , true , nil
209
+ }
210
+ if mc .cfg .tls != nil || mc .cfg .Net == "unix" {
211
+ // write cleartext auth packet
212
+ return []byte (mc .cfg .Passwd ), true , nil // TODO: nul-terminate
213
+ }
214
+ // request public key
215
+ // TODO: allow to specify a local file with the pub key via the DSN
216
+ return []byte {1 }, false , nil
217
+
190
218
default :
191
219
errLog .Print ("unknown auth plugin:" , plugin )
192
220
return nil , false , ErrUnknownPlugin
@@ -223,6 +251,7 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
223
251
if err != nil {
224
252
return err
225
253
}
254
+
226
255
// Do not allow to change the auth plugin more than once
227
256
if newPlugin != "" {
228
257
return ErrMalformPkt
@@ -251,8 +280,6 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
251
280
return err
252
281
}
253
282
} else {
254
- seed := oldAuthData
255
-
256
283
// TODO: allow to specify a local file with the pub key via
257
284
// the DSN
258
285
@@ -274,25 +301,12 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
274
301
}
275
302
276
303
// send encrypted password
277
- plain := make ([]byte , len (mc .cfg .Passwd )+ 1 )
278
- copy (plain , mc .cfg .Passwd )
279
- for i := range plain {
280
- j := i % len (seed )
281
- plain [i ] ^= seed [j ]
282
- }
283
- sha1 := sha1 .New ()
284
- enc , err := rsa .EncryptOAEP (sha1 , rand .Reader , pub .(* rsa.PublicKey ), plain , nil )
304
+ err = mc .sendEncryptedPassword (oldAuthData , pub .(* rsa.PublicKey ))
285
305
if err != nil {
286
306
return err
287
307
}
288
-
289
- if err = mc .writeAuthSwitchPacket (enc , false ); err != nil {
290
- return err
291
- }
292
- }
293
- if err = mc .readResultOK (); err == nil {
294
- return nil // auth successful
295
308
}
309
+ return mc .readResultOK ()
296
310
297
311
default :
298
312
return ErrMalformPkt
@@ -301,6 +315,20 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
301
315
return ErrMalformPkt
302
316
}
303
317
318
+ case "sha256_password" :
319
+ block , _ := pem .Decode (authData )
320
+ pub , err := x509 .ParsePKIXPublicKey (block .Bytes )
321
+ if err != nil {
322
+ return err
323
+ }
324
+
325
+ // send encrypted password
326
+ err = mc .sendEncryptedPassword (oldAuthData , pub .(* rsa.PublicKey ))
327
+ if err != nil {
328
+ return err
329
+ }
330
+ return mc .readResultOK ()
331
+
304
332
default :
305
333
return nil // auth successful
306
334
}
0 commit comments