opensmtpd-filter-dkimout/src/config.rs

127 lines
3.3 KiB
Rust
Raw Normal View History

2023-03-26 17:15:41 +02:00
use crate::algorithm::Algorithm;
2023-03-26 16:30:53 +02:00
use crate::canonicalization::Canonicalization;
2023-03-26 16:07:49 +02:00
use clap::Parser;
use std::collections::HashSet;
use std::fs::File;
use std::io::{BufRead, BufReader};
2023-03-26 21:57:01 +02:00
use std::num::NonZeroU64;
2023-03-26 16:07:49 +02:00
use std::path::PathBuf;
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
pub struct Config {
2023-03-26 17:15:41 +02:00
#[arg(short, long, default_value_t = Algorithm::default())]
algorithm: Algorithm,
2023-03-26 16:30:53 +02:00
#[arg(short, long, default_value_t = Canonicalization::default())]
canonicalization: Canonicalization,
2023-03-26 16:07:49 +02:00
#[arg(short, long)]
domain: Vec<String>,
#[arg(short = 'D', long, value_name = "FILE")]
domain_file: Option<PathBuf>,
#[arg(short = 'f', long, value_name = "FILE")]
revocation_list: Option<PathBuf>,
2023-03-26 17:52:15 +02:00
#[arg(short, long)]
header: Vec<String>,
#[arg(short = 'o', long)]
header_optional: Vec<String>,
2023-03-26 21:57:01 +02:00
#[arg(short = 'p', long, default_value_t = NonZeroU64::new(15552000).unwrap())]
cryptoperiod: NonZeroU64,
2023-03-26 22:04:15 +02:00
#[arg(short, long, default_value_t = 1728000)]
revocation: u64,
2023-03-26 22:09:19 +02:00
#[arg(short = 'u', long)]
dns_update_cmd: String,
2023-03-26 21:49:34 +02:00
#[arg(short, long, action = clap::ArgAction::Count)]
verbose: u8,
#[arg(short = 'x', long, default_value_t = 1296000)]
expiration: u64,
2023-03-26 16:07:49 +02:00
}
impl Config {
pub fn init() -> Result<Self, String> {
let mut cnf = Self::parse();
2023-03-26 18:02:20 +02:00
cnf.domain = process_domains(&cnf.domain, &cnf.domain_file)?;
2023-03-26 17:52:15 +02:00
cnf.header = process_headers(&cnf.header, crate::DEFAULT_HEADERS);
cnf.header_optional = process_headers(&cnf.header_optional, crate::DEFAULT_HEADERS_OPT);
2023-03-26 16:07:49 +02:00
Ok(cnf)
}
2023-03-26 17:15:41 +02:00
pub fn algorithm(&self) -> Algorithm {
self.algorithm
}
2023-03-26 16:30:53 +02:00
pub fn canonicalization(&self) -> Canonicalization {
self.canonicalization
}
2023-03-26 16:07:49 +02:00
pub fn domains(&self) -> &[String] {
&self.domain
}
2023-03-26 17:21:20 +02:00
2023-03-26 17:52:15 +02:00
pub fn headers(&self) -> &[String] {
&self.header
}
pub fn headers_optional(&self) -> &[String] {
&self.header_optional
}
2023-03-26 21:49:34 +02:00
pub fn cryptoperiod(&self) -> NonZeroU64 {
self.cryptoperiod
}
2023-03-26 22:04:15 +02:00
pub fn revocation(&self) -> u64 {
self.revocation
}
pub fn dns_update_cmd(&self) -> &str {
&self.dns_update_cmd
}
2023-03-26 21:49:34 +02:00
pub fn verbosity(&self) -> log::LevelFilter {
crate::logs::log_level(self.verbose)
}
pub fn expiration(&self) -> Option<u64> {
if self.expiration != 0 {
Some(self.expiration)
} else {
None
}
}
2023-03-26 17:52:15 +02:00
}
2023-03-26 18:02:20 +02:00
fn process_domains(lst: &[String], domain_file: &Option<PathBuf>) -> Result<Vec<String>, String> {
let mut domain_set: HashSet<String> = lst.iter().map(|e| e.to_string()).collect();
if let Some(path) = domain_file {
let f = File::open(path).map_err(|e| format!("{}: {e}", path.display()))?;
for line in BufReader::new(f).lines() {
let line = line.map_err(|e| format!("{}: {e}", path.display()))?;
let domain = line.trim();
if !domain.is_empty() && !domain.starts_with('#') {
domain_set.insert(domain.to_string().to_lowercase());
}
}
}
Ok(domain_set.into_iter().collect::<Vec<_>>())
}
2023-03-26 17:52:15 +02:00
fn process_headers(lst: &[String], default: &str) -> Vec<String> {
let ret = if lst.is_empty() {
let default_lst = vec![default.to_string()];
do_process_headers(&default_lst)
} else {
do_process_headers(lst)
};
ret.into_iter().collect::<Vec<_>>()
}
fn do_process_headers(lst: &[String]) -> HashSet<String> {
let mut ret = HashSet::with_capacity(128);
for input in lst {
for h in input.split(':') {
ret.insert(h.to_string().to_lowercase());
}
}
ret
2023-03-26 16:07:49 +02:00
}