****************************************************************************** * Initialization Process * ******************************************************************************/ Handshake Initialization Packet https://dev.mysql.com/doc/dev
()
| 182 | // https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_connection_phase_packets_protocol_handshake_v10.html |
| 183 | // https://mariadb.com/kb/en/connection/#initial-handshake-packet |
| 184 | func (mc *mysqlConn) readHandshakePacket() (data []byte, capabilities capabilityFlag, extendedCapabilities extendedCapabilityFlag, plugin string, err error) { |
| 185 | data, err = mc.readPacket() |
| 186 | if err != nil { |
| 187 | return |
| 188 | } |
| 189 | |
| 190 | if data[0] == iERR { |
| 191 | err = mc.handleErrorPacket(data) |
| 192 | return |
| 193 | } |
| 194 | |
| 195 | // protocol version [1 byte] |
| 196 | if data[0] < minProtocolVersion { |
| 197 | return nil, 0, 0, "", fmt.Errorf( |
| 198 | "unsupported protocol version %d. Version %d or higher is required", |
| 199 | data[0], |
| 200 | minProtocolVersion, |
| 201 | ) |
| 202 | } |
| 203 | |
| 204 | // server version [null terminated string] |
| 205 | // connection id [4 bytes] |
| 206 | pos := 1 + bytes.IndexByte(data[1:], 0x00) + 1 + 4 |
| 207 | |
| 208 | // first part of the password cipher [8 bytes] |
| 209 | authData := data[pos : pos+8] |
| 210 | |
| 211 | // (filler) always 0x00 [1 byte] |
| 212 | pos += 8 + 1 |
| 213 | |
| 214 | // capability flags (lower 2 bytes) [2 bytes] |
| 215 | capabilities = capabilityFlag(binary.LittleEndian.Uint16(data[pos : pos+2])) |
| 216 | if capabilities&clientProtocol41 == 0 { |
| 217 | return nil, capabilities, 0, "", ErrOldProtocol |
| 218 | } |
| 219 | if capabilities&clientSSL == 0 && mc.cfg.TLS != nil { |
| 220 | if mc.cfg.AllowFallbackToPlaintext { |
| 221 | mc.cfg.TLS = nil |
| 222 | } else { |
| 223 | return nil, capabilities, 0, "", ErrNoTLS |
| 224 | } |
| 225 | } |
| 226 | pos += 2 |
| 227 | |
| 228 | if len(data) > pos { |
| 229 | // character set [1 byte] |
| 230 | // status flags [2 bytes] |
| 231 | pos += 3 |
| 232 | // capability flags (upper 2 bytes) [2 bytes] |
| 233 | capabilities |= capabilityFlag(binary.LittleEndian.Uint16(data[pos:pos+2])) << 16 |
| 234 | pos += 2 |
| 235 | // length of auth-plugin-data [1 byte] |
| 236 | // reserved (all [00]) [6 bytes] |
| 237 | pos += 7 |
| 238 | if capabilities&clientMySQL == 0 { |
| 239 | // MariaDB server extended flag |
| 240 | extendedCapabilities = extendedCapabilityFlag(binary.LittleEndian.Uint32(data[pos : pos+4])) |
| 241 | } |