| 565 | |
| 566 | |
| 567 | void Connection::receiveHello() |
| 568 | { |
| 569 | /// Receive hello packet. |
| 570 | UInt64 packet_type = 0; |
| 571 | |
| 572 | /// Prevent read after eof in readVarUInt in case of reset connection |
| 573 | /// (Poco should throw such exception while reading from socket but |
| 574 | /// sometimes it doesn't for unknown reason) |
| 575 | if (in->eof()) |
| 576 | throw Poco::Net::NetException("Connection reset by peer"); |
| 577 | |
| 578 | readVarUInt(packet_type, *in); |
| 579 | if (packet_type == Protocol::Server::Hello) |
| 580 | { |
| 581 | readStringBinary(server_name, *in, DBMS_MAX_HELLO_STRING_SIZE); |
| 582 | sanitizeUntrustedServerString(server_name); |
| 583 | readVarUInt(server_version_major, *in); |
| 584 | readVarUInt(server_version_minor, *in); |
| 585 | readVarUInt(server_revision, *in); |
| 586 | if (server_revision >= DBMS_MIN_REVISION_WITH_VERSIONED_PARALLEL_REPLICAS_PROTOCOL) |
| 587 | readVarUInt(server_parallel_replicas_protocol_version, *in); |
| 588 | if (server_revision >= DBMS_MIN_REVISION_WITH_SERVER_TIMEZONE) |
| 589 | { |
| 590 | readStringBinary(server_timezone, *in, DBMS_MAX_HELLO_STRING_SIZE); |
| 591 | sanitizeUntrustedServerString(server_timezone); |
| 592 | } |
| 593 | if (server_revision >= DBMS_MIN_REVISION_WITH_SERVER_DISPLAY_NAME) |
| 594 | { |
| 595 | readStringBinary(server_display_name, *in, DBMS_MAX_HELLO_STRING_SIZE); |
| 596 | sanitizeUntrustedServerString(server_display_name); |
| 597 | } |
| 598 | if (server_revision >= DBMS_MIN_REVISION_WITH_VERSION_PATCH) |
| 599 | readVarUInt(server_version_patch, *in); |
| 600 | else |
| 601 | server_version_patch = server_revision; |
| 602 | |
| 603 | if (server_revision >= DBMS_MIN_PROTOCOL_VERSION_WITH_CHUNKED_PACKETS) |
| 604 | { |
| 605 | /// These are tiny protocol tokens ("chunked" / "notchunked") compared in |
| 606 | /// `is_chunked`; cap them so a hostile server cannot force a large allocation. |
| 607 | readStringBinary(proto_send_chunked_srv, *in, DBMS_MAX_HELLO_STRING_SIZE); |
| 608 | readStringBinary(proto_recv_chunked_srv, *in, DBMS_MAX_HELLO_STRING_SIZE); |
| 609 | } |
| 610 | |
| 611 | if (server_revision >= DBMS_MIN_PROTOCOL_VERSION_WITH_PASSWORD_COMPLEXITY_RULES) |
| 612 | { |
| 613 | UInt64 rules_size = 0; |
| 614 | readVarUInt(rules_size, *in); |
| 615 | /// `rules_size` is server-controlled and feeds a `reserve`; reject absurd |
| 616 | /// values so a hostile server cannot force a huge allocation. The server |
| 617 | /// enforces the same cap at construction time (see TCPHandler::sendHello). |
| 618 | if (rules_size > DBMS_MAX_PASSWORD_COMPLEXITY_RULES) |
| 619 | throw Exception(ErrorCodes::UNEXPECTED_PACKET_FROM_SERVER, |
| 620 | "Server declared {} password-complexity rules, maximum allowed is {}", |
| 621 | rules_size, DBMS_MAX_PASSWORD_COMPLEXITY_RULES); |
| 622 | password_complexity_rules.reserve(rules_size); |
| 623 | |
| 624 | for (size_t i = 0; i < rules_size; ++i) |
nothing calls this directly
no test coverage detected