From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 5282591C4B for ; Tue, 4 Apr 2023 09:49:05 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 19B6919257 for ; Tue, 4 Apr 2023 09:48:35 +0200 (CEST) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS for ; Tue, 4 Apr 2023 09:48:34 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id A847D45812 for ; Tue, 4 Apr 2023 09:48:33 +0200 (CEST) From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= To: pve-devel@lists.proxmox.com Date: Tue, 4 Apr 2023 09:48:21 +0200 Message-Id: <20230404074821.3765099-3-f.gruenbichler@proxmox.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230404074821.3765099-1-f.gruenbichler@proxmox.com> References: <20230404074821.3765099-1-f.gruenbichler@proxmox.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.072 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 Subject: [pve-devel] [PATCH proxmox-offline-mirror 2/2] fix #4632: allow escape hatches for legacy repositories X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 04 Apr 2023 07:49:05 -0000 there are still repositories out there that are using things like DSA/RSA-1024 and SHA1, so let's allow POM users to opt into accepting those insecure cryptographic parameters, but keep the default settings secure. Signed-off-by: Fabian Grünbichler --- src/bin/proxmox-offline-mirror.rs | 2 + src/bin/proxmox_offline_mirror_cmds/config.rs | 4 ++ src/config.rs | 42 ++++++++++++++++++- src/helpers/verifier.rs | 20 ++++++++- src/mirror.rs | 17 +++++++- 5 files changed, 81 insertions(+), 4 deletions(-) diff --git a/src/bin/proxmox-offline-mirror.rs b/src/bin/proxmox-offline-mirror.rs index 3af33bb..bec366a 100644 --- a/src/bin/proxmox-offline-mirror.rs +++ b/src/bin/proxmox-offline-mirror.rs @@ -423,6 +423,7 @@ fn action_add_mirror(config: &SectionConfigData) -> Result, Er use_subscription: None, ignore_errors: false, skip, + weak_crypto: None, }); } } @@ -438,6 +439,7 @@ fn action_add_mirror(config: &SectionConfigData) -> Result, Er use_subscription, ignore_errors: false, skip, + weak_crypto: None, }; configs.push(main_config); diff --git a/src/bin/proxmox_offline_mirror_cmds/config.rs b/src/bin/proxmox_offline_mirror_cmds/config.rs index 3ebf4ad..696da11 100644 --- a/src/bin/proxmox_offline_mirror_cmds/config.rs +++ b/src/bin/proxmox_offline_mirror_cmds/config.rs @@ -274,6 +274,10 @@ pub fn update_mirror( data.skip.skip_sections = Some(skip_sections); } + if let Some(weak_crypto) = update.weak_crypto { + data.weak_crypto = Some(weak_crypto); + } + config.set_data(&id, "mirror", &data)?; proxmox_offline_mirror::config::save_config(&config_file, &config)?; diff --git a/src/config.rs b/src/config.rs index 39b1193..0e19c77 100644 --- a/src/config.rs +++ b/src/config.rs @@ -5,7 +5,7 @@ use lazy_static::lazy_static; use proxmox_subscription::{sign::ServerBlob, SubscriptionInfo}; use serde::{Deserialize, Serialize}; -use proxmox_schema::{api, ApiType, Schema, Updater}; +use proxmox_schema::{api, ApiStringFormat, ApiType, Schema, Updater}; use proxmox_section_config::{SectionConfig, SectionConfigData, SectionConfigPlugin}; use proxmox_sys::fs::{replace_file, CreateOptions}; @@ -46,6 +46,38 @@ pub struct SkipConfig { pub skip_packages: Option>, } +#[api( + properties: { + "allow-sha1": { + type: bool, + default: false, + optional: true, + }, + "min-dsa-key-size": { + type: u64, + optional: true, + }, + "min-rsa-key-size": { + type: u64, + optional: true, + }, + }, +)] +#[derive(Default, Serialize, Deserialize, Updater, Clone, Debug)] +#[serde(rename_all = "kebab-case")] +/// Weak Cryptography Configuration +pub struct WeakCryptoConfig { + /// Whether to allow SHA-1 based signatures + #[serde(default)] + pub allow_sha1: bool, + /// Whether to lower the key size cutoff for DSA-based signatures + #[serde(default)] + pub min_dsa_key_size: Option, + /// Whether to lower the key size cutoff for RSA-based signatures + #[serde(default)] + pub min_rsa_key_size: Option, +} + #[api( properties: { id: { @@ -81,6 +113,11 @@ pub struct SkipConfig { "skip": { type: SkipConfig, }, + "weak-crypto": { + type: String, + optional: true, + format: &ApiStringFormat::PropertyString(&WeakCryptoConfig::API_SCHEMA), + }, } )] #[derive(Clone, Debug, Serialize, Deserialize, Updater)] @@ -111,6 +148,9 @@ pub struct MirrorConfig { /// Skip package files using these criteria #[serde(default, flatten)] pub skip: SkipConfig, + /// Whether to allow using weak cryptography algorithms or parameters, deviating from the default policy. + #[serde(default)] + pub weak_crypto: Option, } #[api( diff --git a/src/helpers/verifier.rs b/src/helpers/verifier.rs index 131bccd..e38ef40 100644 --- a/src/helpers/verifier.rs +++ b/src/helpers/verifier.rs @@ -9,10 +9,13 @@ use sequoia_openpgp::{ Parse, }, policy::StandardPolicy, + types::HashAlgorithm, Cert, KeyHandle, }; use std::io; +use crate::config::WeakCryptoConfig; + struct Helper<'a> { cert: &'a Cert, } @@ -91,10 +94,25 @@ pub(crate) fn verify_signature<'msg>( msg: &'msg [u8], key: &[u8], detached_sig: Option<&[u8]>, + weak_crypto: &WeakCryptoConfig, ) -> Result, Error> { let cert = Cert::from_bytes(key)?; - let policy = StandardPolicy::new(); + let mut policy = StandardPolicy::new(); + if weak_crypto.allow_sha1 { + policy.accept_hash(HashAlgorithm::SHA1); + } + if let Some(min_dsa) = weak_crypto.min_dsa_key_size { + if min_dsa <= 1024 { + policy.accept_asymmetric_algo(sequoia_openpgp::policy::AsymmetricAlgorithm::DSA1024); + } + } + if let Some(min_rsa) = weak_crypto.min_dsa_key_size { + if min_rsa <= 1024 { + policy.accept_asymmetric_algo(sequoia_openpgp::policy::AsymmetricAlgorithm::RSA1024); + } + } + let helper = Helper { cert: &cert }; let verified = if let Some(sig) = detached_sig { diff --git a/src/mirror.rs b/src/mirror.rs index 0dc0751..3766f23 100644 --- a/src/mirror.rs +++ b/src/mirror.rs @@ -10,10 +10,11 @@ use flate2::bufread::GzDecoder; use globset::{Glob, GlobSet, GlobSetBuilder}; use nix::libc; use proxmox_http::{client::sync::Client, HttpClient, HttpOptions, ProxyConfig}; +use proxmox_schema::{ApiType, Schema}; use proxmox_sys::fs::file_get_contents; use crate::{ - config::{MirrorConfig, SkipConfig, SubscriptionKey}, + config::{MirrorConfig, SkipConfig, SubscriptionKey, WeakCryptoConfig}, convert_repo_line, pool::Pool, types::{Diff, Snapshot, SNAPSHOT_REGEX}, @@ -50,6 +51,7 @@ struct ParsedMirrorConfig { pub client: Client, pub ignore_errors: bool, pub skip: SkipConfig, + pub weak_crypto: WeakCryptoConfig, } impl TryInto for MirrorConfig { @@ -72,6 +74,15 @@ impl TryInto for MirrorConfig { let client = Client::new(options); + let weak_crypto = match self.weak_crypto { + Some(property_string) => { + let value = (WeakCryptoConfig::API_SCHEMA as Schema) + .parse_property_string(&property_string)?; + serde_json::from_value(value)? + } + None => WeakCryptoConfig::default(), + }; + Ok(ParsedMirrorConfig { repository, architectures: self.architectures, @@ -83,6 +94,7 @@ impl TryInto for MirrorConfig { client, ignore_errors: self.ignore_errors, skip: self.skip, + weak_crypto, }) } } @@ -208,7 +220,8 @@ fn fetch_release( println!("Verifying '{name}' signature using provided repository key.."); let content = fetched.data_ref(); - let verified = helpers::verify_signature(content, &config.key, sig.as_deref())?; + let verified = + helpers::verify_signature(content, &config.key, sig.as_deref(), &config.weak_crypto)?; println!("Success"); let sha512 = Some(openssl::sha::sha512(content)); -- 2.30.2