Refactoring loading of config file

- let `HuskConfig::load` return a `Result` instead of an `Option`.
- added comments
This commit is contained in:
Malte Meiboom
2026-01-05 12:32:30 +01:00
parent a56e933e80
commit b7e01a446c
7 changed files with 36 additions and 15 deletions
+7 -6
View File
@@ -2,10 +2,13 @@
// Parsing the config file // Parsing the config file
// //
use anyhow;
use std::fs; use std::fs;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use serde_derive::Deserialize; use serde_derive::Deserialize;
use crate::types::errors::HuskError;
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]
pub struct HuskConfig { pub struct HuskConfig {
pub connection: String, pub connection: String,
@@ -15,20 +18,18 @@ pub struct HuskConfig {
impl HuskConfig { impl HuskConfig {
pub fn load(path: &String) -> Option<Self> { pub fn load(path: &String) -> anyhow::Result<Self> {
match fs::read_to_string(path) { match fs::read_to_string(path) {
Ok(data) => { Ok(data) => {
match toml::from_str(data.as_str()) { match toml::from_str(data.as_str()) {
Ok(configuration) => Some(configuration), Ok(configuration) => Ok(configuration),
Err(e) => { Err(e) => {
eprintln!("Error while parsing config file: {:?}", e); Err(HuskError::ConfigFileParseError(e.to_string()).into())
None
} }
} }
}, },
Err(e) => { Err(e) => {
eprintln!("Error while reading config file: {:?}", e); Err(HuskError::ConfigFileOpenError(e.to_string()).into())
None
} }
} }
} }
+8
View File
@@ -24,6 +24,8 @@ use crate::types::husk_context::HuskContext;
use crate::types::introducer::Introducer; use crate::types::introducer::Introducer;
use crate::types::recipient::Recipient; use crate::types::recipient::Recipient;
/// Returns the local trust root from the cert_store. If the trust root
/// cannot be found, it returns an error.
pub fn get_local_trust_root(cert_store: &CertStore) -> anyhow::Result<Cert> { pub fn get_local_trust_root(cert_store: &CertStore) -> anyhow::Result<Cert> {
let root = cert_store.certd() let root = cert_store.certd()
@@ -59,6 +61,9 @@ pub fn get_local_trust_root(cert_store: &CertStore) -> anyhow::Result<Cert> {
} }
/// Returns all certificates with an authenticated binding to user id 'email'.
/// The certificates are not checked for usefulness (for instance, they might
/// miss an encryption subkey).
pub fn get_certificates<'hc>(context: &HuskContext<'hc>, email: &str) pub fn get_certificates<'hc>(context: &HuskContext<'hc>, email: &str)
-> Vec<Arc<LazyCert<'hc>>> { -> Vec<Arc<LazyCert<'hc>>> {
@@ -90,6 +95,7 @@ pub fn get_certificates<'hc>(context: &HuskContext<'hc>, email: &str)
result result
} }
/// Returns all introducers available in cert_store.
pub fn get_introducers<'c>(cert_store: &CertStore<'c>, policy: &StandardPolicy, local_trust_root: Fingerprint) -> Vec<Introducer> { pub fn get_introducers<'c>(cert_store: &CertStore<'c>, policy: &StandardPolicy, local_trust_root: Fingerprint) -> Vec<Introducer> {
let mut result = Vec::new(); let mut result = Vec::new();
@@ -130,6 +136,7 @@ pub fn get_introducers<'c>(cert_store: &CertStore<'c>, policy: &StandardPolicy,
result result
} }
/// Checks if a message contains the OpenPGP artifacts of an encrypted message.
pub fn is_encrypted(body: &Bytes) -> bool { pub fn is_encrypted(body: &Bytes) -> bool {
let mut ppr = match PacketParser::from_bytes(body) { let mut ppr = match PacketParser::from_bytes(body) {
@@ -158,6 +165,7 @@ pub fn is_encrypted(body: &Bytes) -> bool {
false false
} }
/// Encrypt a message for `recipients`.
pub fn encrypt(context: &HuskContext<'_>, body: &Bytes, recipients: &Vec<Recipient>) pub fn encrypt(context: &HuskContext<'_>, body: &Bytes, recipients: &Vec<Recipient>)
-> anyhow::Result<Bytes> { -> anyhow::Result<Bytes> {
+7 -7
View File
@@ -17,13 +17,13 @@ use daemon::Daemon;
async fn main() { async fn main() {
let config_file = env::args().nth(1).expect("config file missing"); let config_file = env::args().nth(1).expect("config file missing");
let husk_config = HuskConfig::load(&config_file); let husk_config = match HuskConfig::load(&config_file) {
Ok(config) => config,
if husk_config.is_none() { Err(e) => {
eprintln!("Cannot load configuration"); eprintln!("{:?}", e);
process::exit(1); process::exit(1);
} }
let husk_config = husk_config.unwrap(); };
log4rs::init_file(husk_config.logfile_config(), Default::default()).unwrap(); log4rs::init_file(husk_config.logfile_config(), Default::default()).unwrap();
+4
View File
@@ -8,6 +8,10 @@ use thiserror::Error;
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum HuskError { pub enum HuskError {
#[error("Cannot open config file: {0}")]
ConfigFileOpenError(String),
#[error("Error while parsing config file: {0}")]
ConfigFileParseError(String),
#[error("Cannot find local trust root")] #[error("Cannot find local trust root")]
NoLocalTrustRoot, NoLocalTrustRoot,
#[error("Cannot access cert store")] #[error("Cannot access cert store")]
+5 -1
View File
@@ -12,8 +12,11 @@ use crate::types::recipient::Recipient;
#[derive(PartialEq)] #[derive(PartialEq)]
pub enum ProtectionPossibility { pub enum ProtectionPossibility {
// no recipient has a cert
NoProtection, NoProtection,
// some recipients have a cert (but not all)
Partial, Partial,
// all recipients have a cert
Full Full
} }
@@ -82,7 +85,8 @@ impl From<&MailContext<'_>> for ProtectionPossibility {
(true, false) => ProtectionPossibility::Full, (true, false) => ProtectionPossibility::Full,
(true, true) => ProtectionPossibility::Partial, (true, true) => ProtectionPossibility::Partial,
(false, true) => ProtectionPossibility::NoProtection, (false, true) => ProtectionPossibility::NoProtection,
(false, false) => ProtectionPossibility::NoProtection, // this should not occure // (false, false) occurs if there are no recipients
(false, false) => ProtectionPossibility::NoProtection,
} }
} }
} }
+4
View File
@@ -37,10 +37,14 @@ impl TryFrom<CString> for Recipient<'_> {
} }
impl Recipient<'_> { impl Recipient<'_> {
/// check if this Recipient can encrypt.
// XXX: currently this check is naive
pub fn can_encrypt(&self) -> bool { pub fn can_encrypt(&self) -> bool {
if self.certs.len() == 0 { if self.certs.len() == 0 {
return false; return false;
} }
// XXX: add check to see if a cert has encryption capable subkeys
true true
} }
} }