Reads 3 bytes, finds out whether it is SSLRequest or HandshakeResponse packet, starts secure connection, if it is SSLRequest. * Reading is performed from socket instead of ReadBuffer to prevent reading part of SSL handshake. * If we read it from socket, it will be impossible to start SSL connection using Poco. Size of SSLRequest packet payload is 32 bytes, thus we can read at most 36 bytes. *
| 375 | * If we read it from socket, it will be impossible to start SSL connection using Poco. Size of SSLRequest packet payload is 32 bytes, thus we can read at most 36 bytes. |
| 376 | */ |
| 377 | void MySQLHandler::finishHandshake(MySQLProtocol::ConnectionPhase::HandshakeResponse & packet) |
| 378 | { |
| 379 | size_t packet_size = PACKET_HEADER_SIZE + SSL_REQUEST_PAYLOAD_SIZE; |
| 380 | |
| 381 | /// Buffer for SSLRequest or part of HandshakeResponse. |
| 382 | std::vector<char> buf(packet_size); |
| 383 | size_t pos = 0; |
| 384 | |
| 385 | /// Reads at least count and at most packet_size bytes. |
| 386 | auto read_bytes = [this, &buf, &pos, &packet_size](size_t count) -> void { |
| 387 | while (pos < count) |
| 388 | { |
| 389 | int ret = socket().receiveBytes(buf.data() + pos, static_cast<uint32_t>(packet_size - pos)); |
| 390 | if (ret == 0) |
| 391 | { |
| 392 | throw Exception(ErrorCodes::CANNOT_READ_ALL_DATA, "Cannot read all data. Bytes read: {}. Bytes expected: 3", std::to_string(pos)); |
| 393 | } |
| 394 | pos += ret; |
| 395 | } |
| 396 | }; |
| 397 | read_bytes(3); /// We can find out whether it is SSLRequest of HandshakeResponse by first 3 bytes. |
| 398 | |
| 399 | size_t payload_size = unalignedLoad<uint32_t>(buf.data()) & 0xFFFFFFu; |
| 400 | LOG_TRACE(log, "payload size: {}", payload_size); |
| 401 | |
| 402 | if (payload_size == SSL_REQUEST_PAYLOAD_SIZE) |
| 403 | { |
| 404 | finishHandshakeSSL(packet_size, buf.data(), pos, read_bytes, packet); |
| 405 | } |
| 406 | else |
| 407 | { |
| 408 | /// Reading rest of HandshakeResponse. |
| 409 | packet_size = PACKET_HEADER_SIZE + payload_size; |
| 410 | WriteBufferFromOwnString buf_for_handshake_response; |
| 411 | buf_for_handshake_response.write(buf.data(), pos); |
| 412 | copyData(*packet_endpoint->in, buf_for_handshake_response, packet_size - pos); |
| 413 | ReadBufferFromString payload(buf_for_handshake_response.str()); |
| 414 | payload.ignore(PACKET_HEADER_SIZE); |
| 415 | packet.readPayloadWithUnpacked(payload); |
| 416 | packet_endpoint->sequence_id++; |
| 417 | } |
| 418 | } |
| 419 | |
| 420 | void MySQLHandler::authenticate(const String & user_name, const String & auth_plugin_name, const String & initial_auth_response) |
| 421 | { |
nothing calls this directly
no test coverage detected