Skip to content

Commit 20a5764

Browse files
committed
auth: add sha256_password implementation
1 parent affd4c9 commit 20a5764

File tree

1 file changed

+45
-17
lines changed

1 file changed

+45
-17
lines changed

auth.go

+45-17
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,22 @@ func scrambleSHA256Password(scramble []byte, password string) []byte {
154154
return message1
155155
}
156156

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+
157173
func (mc *mysqlConn) auth(authData []byte, plugin string) ([]byte, bool, error) {
158174
switch plugin {
159175
case "caching_sha2_password":
@@ -187,6 +203,18 @@ func (mc *mysqlConn) auth(authData []byte, plugin string) ([]byte, bool, error)
187203
authResp := scramblePassword(authData[:20], mc.cfg.Passwd)
188204
return authResp, false, nil
189205

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+
190218
default:
191219
errLog.Print("unknown auth plugin:", plugin)
192220
return nil, false, ErrUnknownPlugin
@@ -223,6 +251,7 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
223251
if err != nil {
224252
return err
225253
}
254+
226255
// Do not allow to change the auth plugin more than once
227256
if newPlugin != "" {
228257
return ErrMalformPkt
@@ -251,8 +280,6 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
251280
return err
252281
}
253282
} else {
254-
seed := oldAuthData
255-
256283
// TODO: allow to specify a local file with the pub key via
257284
// the DSN
258285

@@ -274,25 +301,12 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
274301
}
275302

276303
// 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))
285305
if err != nil {
286306
return err
287307
}
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
295308
}
309+
return mc.readResultOK()
296310

297311
default:
298312
return ErrMalformPkt
@@ -301,6 +315,20 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
301315
return ErrMalformPkt
302316
}
303317

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+
304332
default:
305333
return nil // auth successful
306334
}

0 commit comments

Comments
 (0)