-
Notifications
You must be signed in to change notification settings - Fork 5.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
server: compatible to old handshake protocol #8812
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -245,12 +245,68 @@ type handshakeResponse41 struct { | |
Attrs map[string]string | ||
} | ||
|
||
// parseOldHandshakeResponseHeader parses the old version handshake header HandshakeResponse320 | ||
func parseOldHandshakeResponseHeader(packet *handshakeResponse41, data []byte) (parsedBytes int, err error) { | ||
// Ensure there are enough data to read: | ||
// https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse320 | ||
log.Debugf("Try to parse hanshake response as Protocol::HandshakeResponse320 , packet data: %v", data) | ||
if len(data) < 2+3 { | ||
log.Errorf("Got malformed handshake response, packet data: %v", data) | ||
return 0, mysql.ErrMalformPacket | ||
} | ||
offset := 0 | ||
// capability | ||
capability := binary.LittleEndian.Uint16(data[:2]) | ||
packet.Capability = uint32(capability) | ||
|
||
// be compatible with Protocol::HandshakeResponse41 | ||
packet.Capability = packet.Capability | mysql.ClientProtocol41 | ||
|
||
offset += 2 | ||
// skip max packet size | ||
offset += 3 | ||
// usa default CharsetID | ||
packet.Collation = mysql.CollationNames["utf8mb4_general_ci"] | ||
|
||
return offset, nil | ||
} | ||
|
||
// parseOldHandshakeResponseBody parse the HandshakeResponse for Protocol::HandshakeResponse320 (except the common header part). | ||
func parseOldHandshakeResponseBody(packet *handshakeResponse41, data []byte, offset int) (err error) { | ||
defer func() { | ||
// Check malformat packet cause out of range is disgusting, but don't panic! | ||
if r := recover(); r != nil { | ||
log.Errorf("handshake panic, packet data: %v", data) | ||
err = mysql.ErrMalformPacket | ||
} | ||
}() | ||
// user name | ||
packet.User = string(data[offset : offset+bytes.IndexByte(data[offset:], 0)]) | ||
offset += len(packet.User) + 1 | ||
|
||
if packet.Capability&mysql.ClientConnectWithDB > 0 { | ||
if len(data[offset:]) > 0 { | ||
idx := bytes.IndexByte(data[offset:], 0) | ||
packet.DBName = string(data[offset : offset+idx]) | ||
offset = offset + idx + 1 | ||
} | ||
if len(data[offset:]) > 0 { | ||
packet.Auth = data[offset : offset+bytes.IndexByte(data[offset:], 0)] | ||
offset += len(packet.Auth) + 1 | ||
} | ||
} else { | ||
packet.Auth = data[offset : offset+bytes.IndexByte(data[offset:], 0)] | ||
offset += len(packet.Auth) + 1 | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// parseHandshakeResponseHeader parses the common header of SSLRequest and HandshakeResponse41. | ||
func parseHandshakeResponseHeader(packet *handshakeResponse41, data []byte) (parsedBytes int, err error) { | ||
// Ensure there are enough data to read: | ||
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::SSLRequest | ||
if len(data) < 4+4+1+23 { | ||
log.Errorf("Got malformed handshake response, packet data: %v", data) | ||
return 0, mysql.ErrMalformPacket | ||
} | ||
|
||
|
@@ -365,11 +421,21 @@ func (cc *clientConn) readOptionalSSLRequestAndHandshakeResponse() error { | |
return errors.Trace(err) | ||
} | ||
|
||
isOldVersion := false | ||
|
||
var resp handshakeResponse41 | ||
|
||
pos, err := parseHandshakeResponseHeader(&resp, data) | ||
if err != nil { | ||
return errors.Trace(err) | ||
if err == mysql.ErrMalformPacket { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
https://dev.mysql.com/doc/internals/en/connection-phase-packets.html @imtbkcat can we direct use parse handshake twice has risk |
||
pos, err = parseOldHandshakeResponseHeader(&resp, data) | ||
if err != nil { | ||
return errors.Trace(err) | ||
} | ||
isOldVersion = true | ||
} else { | ||
return errors.Trace(err) | ||
} | ||
} | ||
|
||
if (resp.Capability&mysql.ClientSSL > 0) && cc.server.tlsConfig != nil { | ||
|
@@ -382,14 +448,23 @@ func (cc *clientConn) readOptionalSSLRequestAndHandshakeResponse() error { | |
if err != nil { | ||
return errors.Trace(err) | ||
} | ||
pos, err = parseHandshakeResponseHeader(&resp, data) | ||
if isOldVersion { | ||
pos, err = parseOldHandshakeResponseHeader(&resp, data) | ||
} else { | ||
pos, err = parseHandshakeResponseHeader(&resp, data) | ||
} | ||
if err != nil { | ||
return errors.Trace(err) | ||
} | ||
} | ||
|
||
// Read the remaining part of the packet. | ||
if err = parseHandshakeResponseBody(&resp, data, pos); err != nil { | ||
if isOldVersion { | ||
err = parseOldHandshakeResponseBody(&resp, data, pos) | ||
} else { | ||
err = parseHandshakeResponseBody(&resp, data, pos) | ||
} | ||
if err != nil { | ||
return errors.Trace(err) | ||
} | ||
|
||
|
@@ -398,6 +473,7 @@ func (cc *clientConn) readOptionalSSLRequestAndHandshakeResponse() error { | |
cc.dbname = resp.DBName | ||
cc.collation = resp.Collation | ||
cc.attrs = resp.Attrs | ||
|
||
err = cc.openSessionAndDoAuth(resp.Auth) | ||
return errors.Trace(err) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's better to add it back if we don't parse protocol 41 first.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jackysp addressed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!