1use anyhow::{Context, Result};
6use cryptoki::session::UserType;
7use directories::ProjectDirs;
8use serde::Deserialize;
9use std::collections::HashMap;
10use std::os::unix::fs::PermissionsExt;
11use std::path::Path;
12
13use crate::error::HsmError;
14use crate::module;
15
16#[derive(Deserialize)]
17pub struct Profile {
30 pub token: String,
32
33 #[serde(deserialize_with = "module::deserialize_user")]
35 pub user: UserType,
36
37 pub pin: Option<String>,
39}
40
41impl Profile {
42 pub fn load(filename: &Path) -> Result<HashMap<String, Profile>> {
43 let path = if let Some(base) = ProjectDirs::from("org", "opentitan", "hsmtool") {
44 base.config_dir().join(filename)
45 } else {
46 filename.to_owned()
47 };
48 let perm = path
49 .metadata()
50 .context(format!("Accessing {path:?}"))?
51 .permissions()
52 .mode()
53 & 0o777;
54 if perm & 0o077 != 0 {
56 return Err(HsmError::FilePermissionError(perm)).context(format!("Accessing {path:?}"));
57 }
58 let profiles = std::fs::read_to_string(&path).context(format!("Cannot read {path:?}"))?;
59 Ok(serde_annotate::from_str(&profiles)?)
60 }
61}