From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <pbs-devel-bounces@lists.proxmox.com>
Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9])
	by lore.proxmox.com (Postfix) with ESMTPS id B94791FF185
	for <inbox@lore.proxmox.com>; Wed, 21 May 2025 10:45:57 +0200 (CEST)
Received: from firstgate.proxmox.com (localhost [127.0.0.1])
	by firstgate.proxmox.com (Proxmox) with ESMTP id D731512C40;
	Wed, 21 May 2025 10:45:58 +0200 (CEST)
From: Dominik Csapak <d.csapak@proxmox.com>
To: pbs-devel@lists.proxmox.com
Date: Wed, 21 May 2025 10:45:21 +0200
Message-Id: <20250521084524.829496-3-d.csapak@proxmox.com>
X-Mailer: git-send-email 2.39.5
In-Reply-To: <20250521084524.829496-1-d.csapak@proxmox.com>
References: <20250521084524.829496-1-d.csapak@proxmox.com>
MIME-Version: 1.0
X-SPAM-LEVEL: Spam detection results:  0
 AWL 0.021 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
 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to
 Validity was blocked. See
 https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more
 information.
 RCVD_IN_VALIDITY_RPBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to
 Validity was blocked. See
 https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more
 information.
 RCVD_IN_VALIDITY_SAFE_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to
 Validity was blocked. See
 https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more
 information.
 SPF_HELO_NONE           0.001 SPF: HELO does not publish an SPF Record
 SPF_PASS               -0.001 SPF: sender matches SPF record
Subject: [pbs-devel] [PATCH proxmox 2/2] client: use proxmox-http's openssl
 verification callback
X-BeenThere: pbs-devel@lists.proxmox.com
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Proxmox Backup Server development discussion
 <pbs-devel.lists.proxmox.com>
List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pbs-devel>, 
 <mailto:pbs-devel-request@lists.proxmox.com?subject=unsubscribe>
List-Archive: <http://lists.proxmox.com/pipermail/pbs-devel/>
List-Post: <mailto:pbs-devel@lists.proxmox.com>
List-Help: <mailto:pbs-devel-request@lists.proxmox.com?subject=help>
List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel>, 
 <mailto:pbs-devel-request@lists.proxmox.com?subject=subscribe>
Reply-To: Proxmox Backup Server development discussion
 <pbs-devel@lists.proxmox.com>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Errors-To: pbs-devel-bounces@lists.proxmox.com
Sender: "pbs-devel" <pbs-devel-bounces@lists.proxmox.com>

This changes the validation logic by always checking the fingerprint of
the leaf certificate, ignoring the openssl verification if a fingerprint
is configured. This now aligns with our perl implementation and the one
for proxmox-websocket-tunnel.

Before, a valid certificate chain would have precedence over an explicit
fingerprint.

Additionally, fingerprints will be correctly checked only against the
leaf certificate instead of every part of the chain for which the
callback is called.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 proxmox-client/Cargo.toml    |  2 +-
 proxmox-client/src/client.rs | 48 ++++++------------------------------
 2 files changed, 9 insertions(+), 41 deletions(-)

diff --git a/proxmox-client/Cargo.toml b/proxmox-client/Cargo.toml
index c2682e77..477e9393 100644
--- a/proxmox-client/Cargo.toml
+++ b/proxmox-client/Cargo.toml
@@ -24,7 +24,7 @@ openssl = { workspace = true, optional = true }
 
 proxmox-login = { workspace = true, features = [ "http" ] }
 
-proxmox-http = { workspace = true, optional = true, features = [ "client" ] }
+proxmox-http = { workspace = true, optional = true, features = [ "client", "tls" ] }
 hyper = { workspace = true, optional = true }
 
 [dev-dependencies]
diff --git a/proxmox-client/src/client.rs b/proxmox-client/src/client.rs
index 6f1c9ef1..ce0c4841 100644
--- a/proxmox-client/src/client.rs
+++ b/proxmox-client/src/client.rs
@@ -9,9 +9,9 @@ use http::uri::PathAndQuery;
 use http::Method;
 use http::{StatusCode, Uri};
 use hyper::body::{Body, HttpBody};
-use openssl::hash::MessageDigest;
 use openssl::ssl::{SslConnector, SslMethod, SslVerifyMode};
 use openssl::x509::{self, X509};
+use proxmox_http::get_fingerprint_from_u8;
 use proxmox_login::Ticket;
 use serde::Serialize;
 
@@ -109,10 +109,14 @@ impl Client {
             TlsOptions::Insecure => connector.set_verify(SslVerifyMode::NONE),
             TlsOptions::Fingerprint(expected_fingerprint) => {
                 connector.set_verify_callback(SslVerifyMode::PEER, move |valid, chain| {
-                    if valid {
-                        return true;
+                    let fp = get_fingerprint_from_u8(&expected_fingerprint);
+                    match proxmox_http::openssl_verify_callback(valid, chain, Some(&fp)) {
+                        Ok(()) => true,
+                        Err(err) => {
+                            log::error!("{err}");
+                            false
+                        }
                     }
-                    verify_fingerprint(chain, &expected_fingerprint)
                 });
             }
             TlsOptions::Callback(cb) => {
@@ -543,42 +547,6 @@ impl HttpApiClient for Client {
     }
 }
 
-fn verify_fingerprint(chain: &x509::X509StoreContextRef, expected_fingerprint: &[u8]) -> bool {
-    let Some(cert) = chain.current_cert() else {
-        log::error!("no certificate in chain?");
-        return false;
-    };
-
-    let fp = match cert.digest(MessageDigest::sha256()) {
-        Err(err) => {
-            log::error!("error calculating certificate fingerprint: {err}");
-            return false;
-        }
-        Ok(fp) => fp,
-    };
-
-    if expected_fingerprint != fp.as_ref() {
-        log::error!("bad fingerprint: {}", fp_string(&fp));
-        log::error!("expected fingerprint: {}", fp_string(expected_fingerprint));
-        return false;
-    }
-
-    true
-}
-
-fn fp_string(fp: &[u8]) -> String {
-    use std::fmt::Write as _;
-
-    let mut out = String::new();
-    for b in fp {
-        if !out.is_empty() {
-            out.push(':');
-        }
-        let _ = write!(out, "{b:02x}");
-    }
-    out
-}
-
 impl Error {
     pub(crate) fn internal<E>(context: &'static str, err: E) -> Self
     where
-- 
2.39.5



_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel