Skip to content

Commit 369b5d6

Browse files
authored
Fix Auth Resnponse packet for cleartext password (go-sql-driver#887)
Trailing NUL char should be in `string[n] auth-response`. But NUL was after auth-response.
1 parent fd197cd commit 369b5d6

File tree

4 files changed

+64
-75
lines changed

4 files changed

+64
-75
lines changed

auth.go

+18-18
Original file line numberDiff line numberDiff line change
@@ -234,64 +234,64 @@ func (mc *mysqlConn) sendEncryptedPassword(seed []byte, pub *rsa.PublicKey) erro
234234
if err != nil {
235235
return err
236236
}
237-
return mc.writeAuthSwitchPacket(enc, false)
237+
return mc.writeAuthSwitchPacket(enc)
238238
}
239239

240-
func (mc *mysqlConn) auth(authData []byte, plugin string) ([]byte, bool, error) {
240+
func (mc *mysqlConn) auth(authData []byte, plugin string) ([]byte, error) {
241241
switch plugin {
242242
case "caching_sha2_password":
243243
authResp := scrambleSHA256Password(authData, mc.cfg.Passwd)
244-
return authResp, false, nil
244+
return authResp, nil
245245

246246
case "mysql_old_password":
247247
if !mc.cfg.AllowOldPasswords {
248-
return nil, false, ErrOldPassword
248+
return nil, ErrOldPassword
249249
}
250250
// Note: there are edge cases where this should work but doesn't;
251251
// this is currently "wontfix":
252252
// https://github.com/go-sql-driver/mysql/issues/184
253-
authResp := scrambleOldPassword(authData[:8], mc.cfg.Passwd)
254-
return authResp, true, nil
253+
authResp := append(scrambleOldPassword(authData[:8], mc.cfg.Passwd), 0)
254+
return authResp, nil
255255

256256
case "mysql_clear_password":
257257
if !mc.cfg.AllowCleartextPasswords {
258-
return nil, false, ErrCleartextPassword
258+
return nil, ErrCleartextPassword
259259
}
260260
// http://dev.mysql.com/doc/refman/5.7/en/cleartext-authentication-plugin.html
261261
// http://dev.mysql.com/doc/refman/5.7/en/pam-authentication-plugin.html
262-
return []byte(mc.cfg.Passwd), true, nil
262+
return append([]byte(mc.cfg.Passwd), 0), nil
263263

264264
case "mysql_native_password":
265265
if !mc.cfg.AllowNativePasswords {
266-
return nil, false, ErrNativePassword
266+
return nil, ErrNativePassword
267267
}
268268
// https://dev.mysql.com/doc/internals/en/secure-password-authentication.html
269269
// Native password authentication only need and will need 20-byte challenge.
270270
authResp := scramblePassword(authData[:20], mc.cfg.Passwd)
271-
return authResp, false, nil
271+
return authResp, nil
272272

273273
case "sha256_password":
274274
if len(mc.cfg.Passwd) == 0 {
275-
return nil, true, nil
275+
return []byte{0}, nil
276276
}
277277
if mc.cfg.tls != nil || mc.cfg.Net == "unix" {
278278
// write cleartext auth packet
279-
return []byte(mc.cfg.Passwd), true, nil
279+
return append([]byte(mc.cfg.Passwd), 0), nil
280280
}
281281

282282
pubKey := mc.cfg.pubKey
283283
if pubKey == nil {
284284
// request public key from server
285-
return []byte{1}, false, nil
285+
return []byte{1}, nil
286286
}
287287

288288
// encrypted password
289289
enc, err := encryptPassword(mc.cfg.Passwd, authData, pubKey)
290-
return enc, false, err
290+
return enc, err
291291

292292
default:
293293
errLog.Print("unknown auth plugin:", plugin)
294-
return nil, false, ErrUnknownPlugin
294+
return nil, ErrUnknownPlugin
295295
}
296296
}
297297

@@ -315,11 +315,11 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
315315

316316
plugin = newPlugin
317317

318-
authResp, addNUL, err := mc.auth(authData, plugin)
318+
authResp, err := mc.auth(authData, plugin)
319319
if err != nil {
320320
return err
321321
}
322-
if err = mc.writeAuthSwitchPacket(authResp, addNUL); err != nil {
322+
if err = mc.writeAuthSwitchPacket(authResp); err != nil {
323323
return err
324324
}
325325

@@ -352,7 +352,7 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
352352
case cachingSha2PasswordPerformFullAuthentication:
353353
if mc.cfg.tls != nil || mc.cfg.Net == "unix" {
354354
// write cleartext auth packet
355-
err = mc.writeAuthSwitchPacket([]byte(mc.cfg.Passwd), true)
355+
err = mc.writeAuthSwitchPacket(append([]byte(mc.cfg.Passwd), 0))
356356
if err != nil {
357357
return err
358358
}

auth_test.go

+37-36
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,11 @@ func TestAuthFastCachingSHA256PasswordCached(t *testing.T) {
8585
plugin := "caching_sha2_password"
8686

8787
// Send Client Authentication Packet
88-
authResp, addNUL, err := mc.auth(authData, plugin)
88+
authResp, err := mc.auth(authData, plugin)
8989
if err != nil {
9090
t.Fatal(err)
9191
}
92-
err = mc.writeHandshakeResponsePacket(authResp, addNUL, plugin)
92+
err = mc.writeHandshakeResponsePacket(authResp, plugin)
9393
if err != nil {
9494
t.Fatal(err)
9595
}
@@ -130,11 +130,11 @@ func TestAuthFastCachingSHA256PasswordEmpty(t *testing.T) {
130130
plugin := "caching_sha2_password"
131131

132132
// Send Client Authentication Packet
133-
authResp, addNUL, err := mc.auth(authData, plugin)
133+
authResp, err := mc.auth(authData, plugin)
134134
if err != nil {
135135
t.Fatal(err)
136136
}
137-
err = mc.writeHandshakeResponsePacket(authResp, addNUL, plugin)
137+
err = mc.writeHandshakeResponsePacket(authResp, plugin)
138138
if err != nil {
139139
t.Fatal(err)
140140
}
@@ -172,11 +172,11 @@ func TestAuthFastCachingSHA256PasswordFullRSA(t *testing.T) {
172172
plugin := "caching_sha2_password"
173173

174174
// Send Client Authentication Packet
175-
authResp, addNUL, err := mc.auth(authData, plugin)
175+
authResp, err := mc.auth(authData, plugin)
176176
if err != nil {
177177
t.Fatal(err)
178178
}
179-
err = mc.writeHandshakeResponsePacket(authResp, addNUL, plugin)
179+
err = mc.writeHandshakeResponsePacket(authResp, plugin)
180180
if err != nil {
181181
t.Fatal(err)
182182
}
@@ -228,11 +228,11 @@ func TestAuthFastCachingSHA256PasswordFullRSAWithKey(t *testing.T) {
228228
plugin := "caching_sha2_password"
229229

230230
// Send Client Authentication Packet
231-
authResp, addNUL, err := mc.auth(authData, plugin)
231+
authResp, err := mc.auth(authData, plugin)
232232
if err != nil {
233233
t.Fatal(err)
234234
}
235-
err = mc.writeHandshakeResponsePacket(authResp, addNUL, plugin)
235+
err = mc.writeHandshakeResponsePacket(authResp, plugin)
236236
if err != nil {
237237
t.Fatal(err)
238238
}
@@ -280,11 +280,11 @@ func TestAuthFastCachingSHA256PasswordFullSecure(t *testing.T) {
280280
plugin := "caching_sha2_password"
281281

282282
// Send Client Authentication Packet
283-
authResp, addNUL, err := mc.auth(authData, plugin)
283+
authResp, err := mc.auth(authData, plugin)
284284
if err != nil {
285285
t.Fatal(err)
286286
}
287-
err = mc.writeHandshakeResponsePacket(authResp, addNUL, plugin)
287+
err = mc.writeHandshakeResponsePacket(authResp, plugin)
288288
if err != nil {
289289
t.Fatal(err)
290290
}
@@ -336,7 +336,7 @@ func TestAuthFastCleartextPasswordNotAllowed(t *testing.T) {
336336
plugin := "mysql_clear_password"
337337

338338
// Send Client Authentication Packet
339-
_, _, err := mc.auth(authData, plugin)
339+
_, err := mc.auth(authData, plugin)
340340
if err != ErrCleartextPassword {
341341
t.Errorf("expected ErrCleartextPassword, got %v", err)
342342
}
@@ -353,11 +353,11 @@ func TestAuthFastCleartextPassword(t *testing.T) {
353353
plugin := "mysql_clear_password"
354354

355355
// Send Client Authentication Packet
356-
authResp, addNUL, err := mc.auth(authData, plugin)
356+
authResp, err := mc.auth(authData, plugin)
357357
if err != nil {
358358
t.Fatal(err)
359359
}
360-
err = mc.writeHandshakeResponsePacket(authResp, addNUL, plugin)
360+
err = mc.writeHandshakeResponsePacket(authResp, plugin)
361361
if err != nil {
362362
t.Fatal(err)
363363
}
@@ -367,8 +367,8 @@ func TestAuthFastCleartextPassword(t *testing.T) {
367367
authRespEnd := authRespStart + 1 + len(authResp)
368368
writtenAuthRespLen := conn.written[authRespStart]
369369
writtenAuthResp := conn.written[authRespStart+1 : authRespEnd]
370-
expectedAuthResp := []byte{115, 101, 99, 114, 101, 116}
371-
if writtenAuthRespLen != 6 || !bytes.Equal(writtenAuthResp, expectedAuthResp) {
370+
expectedAuthResp := []byte{115, 101, 99, 114, 101, 116, 0}
371+
if writtenAuthRespLen != 7 || !bytes.Equal(writtenAuthResp, expectedAuthResp) {
372372
t.Fatalf("unexpected written auth response (%d bytes): %v", writtenAuthRespLen, writtenAuthResp)
373373
}
374374
conn.written = nil
@@ -396,11 +396,11 @@ func TestAuthFastCleartextPasswordEmpty(t *testing.T) {
396396
plugin := "mysql_clear_password"
397397

398398
// Send Client Authentication Packet
399-
authResp, addNUL, err := mc.auth(authData, plugin)
399+
authResp, err := mc.auth(authData, plugin)
400400
if err != nil {
401401
t.Fatal(err)
402402
}
403-
err = mc.writeHandshakeResponsePacket(authResp, addNUL, plugin)
403+
err = mc.writeHandshakeResponsePacket(authResp, plugin)
404404
if err != nil {
405405
t.Fatal(err)
406406
}
@@ -410,9 +410,9 @@ func TestAuthFastCleartextPasswordEmpty(t *testing.T) {
410410
authRespEnd := authRespStart + 1 + len(authResp)
411411
writtenAuthRespLen := conn.written[authRespStart]
412412
writtenAuthResp := conn.written[authRespStart+1 : authRespEnd]
413-
if writtenAuthRespLen != 0 {
414-
t.Fatalf("unexpected written auth response (%d bytes): %v",
415-
writtenAuthRespLen, writtenAuthResp)
413+
expectedAuthResp := []byte{0}
414+
if writtenAuthRespLen != 1 || !bytes.Equal(writtenAuthResp, expectedAuthResp) {
415+
t.Fatalf("unexpected written auth response (%d bytes): %v", writtenAuthRespLen, writtenAuthResp)
416416
}
417417
conn.written = nil
418418

@@ -439,7 +439,7 @@ func TestAuthFastNativePasswordNotAllowed(t *testing.T) {
439439
plugin := "mysql_native_password"
440440

441441
// Send Client Authentication Packet
442-
_, _, err := mc.auth(authData, plugin)
442+
_, err := mc.auth(authData, plugin)
443443
if err != ErrNativePassword {
444444
t.Errorf("expected ErrNativePassword, got %v", err)
445445
}
@@ -455,11 +455,11 @@ func TestAuthFastNativePassword(t *testing.T) {
455455
plugin := "mysql_native_password"
456456

457457
// Send Client Authentication Packet
458-
authResp, addNUL, err := mc.auth(authData, plugin)
458+
authResp, err := mc.auth(authData, plugin)
459459
if err != nil {
460460
t.Fatal(err)
461461
}
462-
err = mc.writeHandshakeResponsePacket(authResp, addNUL, plugin)
462+
err = mc.writeHandshakeResponsePacket(authResp, plugin)
463463
if err != nil {
464464
t.Fatal(err)
465465
}
@@ -498,11 +498,11 @@ func TestAuthFastNativePasswordEmpty(t *testing.T) {
498498
plugin := "mysql_native_password"
499499

500500
// Send Client Authentication Packet
501-
authResp, addNUL, err := mc.auth(authData, plugin)
501+
authResp, err := mc.auth(authData, plugin)
502502
if err != nil {
503503
t.Fatal(err)
504504
}
505-
err = mc.writeHandshakeResponsePacket(authResp, addNUL, plugin)
505+
err = mc.writeHandshakeResponsePacket(authResp, plugin)
506506
if err != nil {
507507
t.Fatal(err)
508508
}
@@ -540,11 +540,11 @@ func TestAuthFastSHA256PasswordEmpty(t *testing.T) {
540540
plugin := "sha256_password"
541541

542542
// Send Client Authentication Packet
543-
authResp, addNUL, err := mc.auth(authData, plugin)
543+
authResp, err := mc.auth(authData, plugin)
544544
if err != nil {
545545
t.Fatal(err)
546546
}
547-
err = mc.writeHandshakeResponsePacket(authResp, addNUL, plugin)
547+
err = mc.writeHandshakeResponsePacket(authResp, plugin)
548548
if err != nil {
549549
t.Fatal(err)
550550
}
@@ -554,7 +554,8 @@ func TestAuthFastSHA256PasswordEmpty(t *testing.T) {
554554
authRespEnd := authRespStart + 1 + len(authResp)
555555
writtenAuthRespLen := conn.written[authRespStart]
556556
writtenAuthResp := conn.written[authRespStart+1 : authRespEnd]
557-
if writtenAuthRespLen != 0 {
557+
expectedAuthResp := []byte{0}
558+
if writtenAuthRespLen != 1 || !bytes.Equal(writtenAuthResp, expectedAuthResp) {
558559
t.Fatalf("unexpected written auth response (%d bytes): %v", writtenAuthRespLen, writtenAuthResp)
559560
}
560561
conn.written = nil
@@ -587,11 +588,11 @@ func TestAuthFastSHA256PasswordRSA(t *testing.T) {
587588
plugin := "sha256_password"
588589

589590
// Send Client Authentication Packet
590-
authResp, addNUL, err := mc.auth(authData, plugin)
591+
authResp, err := mc.auth(authData, plugin)
591592
if err != nil {
592593
t.Fatal(err)
593594
}
594-
err = mc.writeHandshakeResponsePacket(authResp, addNUL, plugin)
595+
err = mc.writeHandshakeResponsePacket(authResp, plugin)
595596
if err != nil {
596597
t.Fatal(err)
597598
}
@@ -636,11 +637,11 @@ func TestAuthFastSHA256PasswordRSAWithKey(t *testing.T) {
636637
plugin := "sha256_password"
637638

638639
// Send Client Authentication Packet
639-
authResp, addNUL, err := mc.auth(authData, plugin)
640+
authResp, err := mc.auth(authData, plugin)
640641
if err != nil {
641642
t.Fatal(err)
642643
}
643-
err = mc.writeHandshakeResponsePacket(authResp, addNUL, plugin)
644+
err = mc.writeHandshakeResponsePacket(authResp, plugin)
644645
if err != nil {
645646
t.Fatal(err)
646647
}
@@ -669,26 +670,26 @@ func TestAuthFastSHA256PasswordSecure(t *testing.T) {
669670
plugin := "sha256_password"
670671

671672
// send Client Authentication Packet
672-
authResp, addNUL, err := mc.auth(authData, plugin)
673+
authResp, err := mc.auth(authData, plugin)
673674
if err != nil {
674675
t.Fatal(err)
675676
}
676677

677678
// unset TLS config to prevent the actual establishment of a TLS wrapper
678679
mc.cfg.tls = nil
679680

680-
err = mc.writeHandshakeResponsePacket(authResp, addNUL, plugin)
681+
err = mc.writeHandshakeResponsePacket(authResp, plugin)
681682
if err != nil {
682683
t.Fatal(err)
683684
}
684685

685686
// check written auth response
686687
authRespStart := 4 + 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1
687-
authRespEnd := authRespStart + 1 + len(authResp) + 1
688+
authRespEnd := authRespStart + 1 + len(authResp)
688689
writtenAuthRespLen := conn.written[authRespStart]
689690
writtenAuthResp := conn.written[authRespStart+1 : authRespEnd]
690691
expectedAuthResp := []byte{115, 101, 99, 114, 101, 116, 0}
691-
if writtenAuthRespLen != 6 || !bytes.Equal(writtenAuthResp, expectedAuthResp) {
692+
if writtenAuthRespLen != 7 || !bytes.Equal(writtenAuthResp, expectedAuthResp) {
692693
t.Fatalf("unexpected written auth response (%d bytes): %v", writtenAuthRespLen, writtenAuthResp)
693694
}
694695
conn.written = nil

driver.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -114,18 +114,18 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
114114
}
115115

116116
// Send Client Authentication Packet
117-
authResp, addNUL, err := mc.auth(authData, plugin)
117+
authResp, err := mc.auth(authData, plugin)
118118
if err != nil {
119119
// try the default auth plugin, if using the requested plugin failed
120120
errLog.Print("could not use requested auth plugin '"+plugin+"': ", err.Error())
121121
plugin = defaultAuthPlugin
122-
authResp, addNUL, err = mc.auth(authData, plugin)
122+
authResp, err = mc.auth(authData, plugin)
123123
if err != nil {
124124
mc.cleanup()
125125
return nil, err
126126
}
127127
}
128-
if err = mc.writeHandshakeResponsePacket(authResp, addNUL, plugin); err != nil {
128+
if err = mc.writeHandshakeResponsePacket(authResp, plugin); err != nil {
129129
mc.cleanup()
130130
return nil, err
131131
}

0 commit comments

Comments
 (0)