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 7ACA71FF16A for ; Fri, 30 Aug 2024 11:21:53 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id C21E737E6D; Fri, 30 Aug 2024 11:22:21 +0200 (CEST) Date: Fri, 30 Aug 2024 11:21:48 +0200 From: Wolfgang Bumiller To: Shannon Sterz Message-ID: References: <20240808142518.248338-1-s.sterz@proxmox.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20240808142518.248338-1-s.sterz@proxmox.com> X-SPAM-LEVEL: Spam detection results: 0 AWL 0.086 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 T_SCC_BODY_TEXT_LINE -0.01 - URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [verifier.rs, mellanox.com] Subject: [pbs-devel] applied: [PATCH proxmox-offline-mirror] verifier: add ability to verify with keyrings X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox Backup Server development discussion Cc: 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" applied with a minor style followup, thanks On Thu, Aug 08, 2024 at 04:25:18PM GMT, Shannon Sterz wrote: > some vendors don't just provide a single certificate but an entire > keyring for their repositories. apt can handle those gracefully, so > should we. this commit adds the ability to verify a repository's > signatures with a keyring. > > we use `PacketParserEOF` to check if a stream of packets is likely a > single certificate or a keyring. if it is a keyring, we try to verify a > message with all certificates in the ring and only fail if no > certificate can verify the message. > > Reported-by: Maximiliano Sandoval > Signed-off-by: Shannon Sterz > --- > > this came up in the enterprise support, so i can't link the exact ticket > here, but it was about mirroring this mellanox repository: > > https://linux.mellanox.com/public/repo/mlnx_ofed/24.04-0.7.0.0/debian12.1/amd64/ > > mellanox says to install the corresponding keyring with this command: > > ``` > wget -qO - https://www.mellanox.com/downloads/ofed/RPM-GPG-KEY-Mellanox | \ > gpg --dearmor | tee /etc/apt/trusted.gpg.d/mellanox.gpg > ``` > > i tested the below code with this mellanox repo, our no-subscription > repo and the debian security updates repo. > > src/helpers/verifier.rs | 71 +++++++++++++++++++++++++++++------------ > 1 file changed, 51 insertions(+), 20 deletions(-) > > diff --git a/src/helpers/verifier.rs b/src/helpers/verifier.rs > index ed986af..0930bd7 100644 > --- a/src/helpers/verifier.rs > +++ b/src/helpers/verifier.rs > @@ -1,12 +1,13 @@ > -use anyhow::{bail, Error}; > +use anyhow::{bail, format_err, Error}; > > use sequoia_openpgp::{ > + cert::CertParser, > parse::{ > stream::{ > DetachedVerifierBuilder, MessageLayer, MessageStructure, VerificationError, > VerificationHelper, VerifierBuilder, > }, > - Parse, > + PacketParser, PacketParserResult, Parse, > }, > policy::StandardPolicy, > types::HashAlgorithm, > @@ -96,8 +97,6 @@ pub(crate) fn verify_signature( > detached_sig: Option<&[u8]>, > weak_crypto: &WeakCryptoConfig, > ) -> Result, Error> { > - let cert = Cert::from_bytes(key)?; > - > let mut policy = StandardPolicy::new(); > if weak_crypto.allow_sha1 { > policy.accept_hash(HashAlgorithm::SHA1); > @@ -113,23 +112,55 @@ pub(crate) fn verify_signature( > } > } > > - let helper = Helper { cert: &cert }; > - > - let verified = if let Some(sig) = detached_sig { > - let mut verifier = > - DetachedVerifierBuilder::from_bytes(sig)?.with_policy(&policy, None, helper)?; > - verifier.verify_bytes(msg)?; > - msg.to_vec() > - } else { > - let mut verified = Vec::new(); > - let mut verifier = VerifierBuilder::from_bytes(msg)?.with_policy(&policy, None, helper)?; > - let bytes = io::copy(&mut verifier, &mut verified)?; > - println!("{bytes} bytes verified"); > - if !verifier.message_processed() { > - bail!("Failed to verify message!"); > + let verifier = |cert| { > + let helper = Helper { cert: &cert }; > + > + if let Some(sig) = detached_sig { > + let mut verifier = > + DetachedVerifierBuilder::from_bytes(sig)?.with_policy(&policy, None, helper)?; > + verifier.verify_bytes(msg)?; > + Ok(msg.to_vec()) > + } else { > + let mut verified = Vec::new(); > + let mut verifier = > + VerifierBuilder::from_bytes(msg)?.with_policy(&policy, None, helper)?; > + let bytes = io::copy(&mut verifier, &mut verified)?; > + println!("{bytes} bytes verified"); > + if !verifier.message_processed() { > + bail!("Failed to verify message!"); > + } > + Ok(verified) > } > - verified > }; > > - Ok(verified) > + let mut packed_parser = PacketParser::from_bytes(key)?; > + > + // parse all packets to see whether this is a simple certificate or a keyring > + while let PacketParserResult::Some(pp) = packed_parser { > + packed_parser = pp.recurse()?.1; > + } > + > + if let PacketParserResult::EOF(eof) = packed_parser { > + // verify against a single certificate > + if eof.is_cert().is_ok() { > + let cert = Cert::from_bytes(key)?; > + return verifier(cert); > + // verify against a keyring > + } else if eof.is_keyring().is_ok() { > + let packed_parser = PacketParser::from_bytes(key)?; > + > + return CertParser::from(packed_parser) > + // flatten here as we ignore packets that aren't a certificate > + .flatten() > + // keep trying to verify the message until the first certificate that succeeds > + .find_map(|c| verifier(c).ok()) > + // if no certificate verified the message, abort > + .ok_or_else(|| format_err!("No key in keyring could verify the message!")); > + } > + } > + > + // neither a keyring nor a certificate was detect, so we abort here > + Err(format_err!( > + "'key-path' contains neither a keyring nor a certificate, aborting!" > + )) ^ condensed the 3 final lines to a single `bail!()` line. _______________________________________________ pbs-devel mailing list pbs-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel