pub const DEFAULT_CONFIG_FILE: &str = "/etc/yubico/yubikeypiv.conf";
use std::{
env,
fs::File,
io::{BufRead, BufReader},
};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SettingSource {
User,
Admin,
Default,
}
impl Default for SettingSource {
fn default() -> Self {
Self::Default
}
}
#[derive(Copy, Clone, Debug, Default)]
pub struct Setting {
pub value: bool,
pub source: SettingSource,
}
impl Setting {
pub fn get(key: &str, default: bool) -> Self {
Self::from_file(key)
.or_else(|| Self::from_env(key))
.unwrap_or(Self {
value: default,
source: SettingSource::Default,
})
}
fn from_file(key: &str) -> Option<Self> {
if let Ok(file) = File::open(DEFAULT_CONFIG_FILE) {
for line in BufReader::new(file).lines() {
let line = match line {
Ok(line) => line,
_ => continue,
};
if line.starts_with('#') || line.starts_with('\r') || line.starts_with('\n') {
continue;
}
let (name, value) = {
let mut parts = line.splitn(2, '=');
let name = parts.next();
let value = parts.next();
match (name, value, parts.next()) {
(Some(name), Some(value), None) => (name.trim(), value.trim()),
_ => continue,
}
};
if name == key {
return Some(Setting {
source: SettingSource::Admin,
value: value == "1" || value == "true",
});
}
}
}
None
}
fn from_env(key: &str) -> Option<Self> {
env::var(format!("YUBIKEY_PIV_{}", key))
.ok()
.map(|value| Setting {
source: SettingSource::User,
value: value == "1" || value == "true",
})
}
}