From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id 1A9681FF0B4 for ; Tue, 10 Nov 2026 12:07:34 +0100 (CET) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id D9F3721596; Tue, 10 Nov 2026 12:07:33 +0100 (CET) From: "Max R. Carrara" To: pbs-devel@lists.proxmox.com Subject: [PATCH proxmox v3 1/5] rest-server: connection: use enum for TLS handshake check result Date: Tue, 10 Nov 2026 12:07:23 +0100 Message-ID: <20261110110728.144880-2-m.carrara@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20261110110728.144880-1-m.carrara@proxmox.com> References: <20261110110728.144880-1-m.carrara@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1794308850423 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.314 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: FTHEQNBLVEOYMGTWCKBYIYAIJQ5U4XV3 X-Message-ID-Hash: FTHEQNBLVEOYMGTWCKBYIYAIJQ5U4XV3 X-MailFrom: m.carrara@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox Backup Server development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: A plain bool doesn't tell callers what `true` and `false` stand for, and it also can't represent further outcomes of the check, such as the client closing the connection before the check could complete. Therefore, return a dedicated enum instead. Signed-off-by: Max R. Carrara --- proxmox-rest-server/src/connection.rs | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/proxmox-rest-server/src/connection.rs b/proxmox-rest-server/src/connection.rs index 153a44b0..3062c4f7 100644 --- a/proxmox-rest-server/src/connection.rs +++ b/proxmox-rest-server/src/connection.rs @@ -297,10 +297,21 @@ struct AcceptState { struct AcceptFlags { is_debug: bool, } +/// Outcome of checking whether a client initiates a TLS handshake on a new connection. +enum TlsHandshakeCheck { + /// The client sent the beginning of a TLS handshake. + /// + /// See [contains_tls_handshake_fragment] for details on how this is + /// checked. + Initiated, + /// The client sent data that does not start a TLS handshake. + NotInitiated, +} + impl AcceptBuilder { async fn accept_connections( self, listener: TcpListener, acceptor: Arc>, @@ -464,14 +475,14 @@ impl AcceptBuilder { let handshake_res = Self::wait_for_client_tls_handshake(socket_ref, CLIENT_HANDSHAKE_TIMEOUT).await; match handshake_res { - Ok(true) => { + Ok(TlsHandshakeCheck::Initiated) => { Self::do_accept_tls(state, flags, secure_sender).await; } - Ok(false) => { + Ok(TlsHandshakeCheck::NotInitiated) => { let insecure_stream = Box::pin(state.socket); if let Err(send_err) = insecure_sender.send(Ok(insecure_stream)).await { log::error!( "[{peer}] failed to accept connection - connection channel closed: {send_err}" @@ -485,11 +496,11 @@ impl AcceptBuilder { } async fn wait_for_client_tls_handshake( incoming_stream: &TcpStream, timeout: Duration, - ) -> Result { + ) -> Result { const HANDSHAKE_BYTES_LEN: usize = 5; let future = async { let mut previous_peek_len = 0; incoming_stream @@ -525,11 +536,17 @@ impl AcceptBuilder { previous_peek_len = peek_len; Err(io::ErrorKind::WouldBlock.into()) } } // Either we got Ok(HANDSHAKE_BYTES_LEN) or some error. - res => res.map(|_| contains_tls_handshake_fragment(&buf)), + res => res.map(|_| { + if contains_tls_handshake_fragment(&buf) { + TlsHandshakeCheck::Initiated + } else { + TlsHandshakeCheck::NotInitiated + } + }), } }) .await .context("couldn't peek into incoming TCP stream") }; -- 2.47.3