From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id C69111FF14F for ; Wed, 17 Jun 2026 11:00:48 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id D76641AD4F; Wed, 17 Jun 2026 11:00:27 +0200 (CEST) From: Dominik Csapak To: pve-devel@lists.proxmox.com, pbs-devel@lists.proxmox.com Subject: [PATCH proxmox-backup v3 5/6] pbs-client: honor already verified fingerprint Date: Wed, 17 Jun 2026 10:59:17 +0200 Message-ID: <20260617085949.1528300-6-d.csapak@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260617085949.1528300-1-d.csapak@proxmox.com> References: <20260617085949.1528300-1-d.csapak@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.049 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment 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: UNGHAB3PYADHOXKUH5F5FZFCEB7WZENW X-Message-ID-Hash: UNGHAB3PYADHOXKUH5F5FZFCEB7WZENW X-MailFrom: d.csapak@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: When there is an invalid fingerprint or a mismatch and the client is executed in an interactive way, the user is asked if he wants to trust the fingerprint. OpenSSL might evaluate the verify callback multiple times per certificate (for different errors for example), so we have to check if the fingerprint matches the one we already verified. Otherwise the user gets multiple prompts directly after another. Signed-off-by: Dominik Csapak --- pbs-client/src/http_client.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/pbs-client/src/http_client.rs b/pbs-client/src/http_client.rs index ea6e5d7fa..14aa4d317 100644 --- a/pbs-client/src/http_client.rs +++ b/pbs-client/src/http_client.rs @@ -422,6 +422,17 @@ impl HttpClient { let interactive = options.interactive; let fingerprint_cache = options.fingerprint_cache; let prefix = options.prefix.clone(); + let check_fp_verified = + |verified_fingerprint: &Arc>>, fingerprint: &str| -> bool { + let verified = verified_fingerprint.lock().unwrap(); + if let Some(verified) = &*verified { + if verified == fingerprint { + // already verified + return true; + } + } + false + }; ssl_connector_builder.set_verify_callback( openssl::ssl::SslVerifyMode::PEER, move |valid, ctx| match openssl_verify_callback( @@ -439,6 +450,9 @@ impl HttpClient { error!("certificate validation failed - failed to calculate FP - {error_stack}") }, SslVerifyError::UntrustedCertificate { fingerprint } => { + if check_fp_verified(&verified_fingerprint, &fingerprint) { + return true; + } if interactive && std::io::stdin().is_terminal() { match Self::interactive_fp_check(prefix.as_deref(), &server, verified_fingerprint.clone(), fingerprint_cache, fingerprint) { Ok(()) => return true, @@ -447,6 +461,9 @@ impl HttpClient { } } SslVerifyError::FingerprintMismatch { fingerprint, expected } => { + if check_fp_verified(&verified_fingerprint, &fingerprint) { + return true; + } warn!("WARNING: certificate fingerprint does not match expected fingerprint!"); warn!("expected: {expected}"); -- 2.47.3