aboutsummaryrefslogtreecommitdiff
path: root/nitrocli/src/pinentry.rs
diff options
context:
space:
mode:
Diffstat (limited to 'nitrocli/src/pinentry.rs')
-rw-r--r--nitrocli/src/pinentry.rs86
1 files changed, 59 insertions, 27 deletions
diff --git a/nitrocli/src/pinentry.rs b/nitrocli/src/pinentry.rs
index d54a182..1eecdd0 100644
--- a/nitrocli/src/pinentry.rs
+++ b/nitrocli/src/pinentry.rs
@@ -46,34 +46,66 @@ impl str::FromStr for PinType {
}
}
-impl PinType {
- fn cache_id(self) -> &'static str {
- match self {
- PinType::Admin => "nitrocli:admin",
- PinType::User => "nitrocli:user",
+#[derive(Debug)]
+pub struct PinEntry {
+ pin_type: PinType,
+ model: nitrokey::Model,
+ serial: String,
+}
+
+impl PinEntry {
+ pub fn from<D>(pin_type: PinType, device: &D) -> crate::Result<Self>
+ where
+ D: nitrokey::Device,
+ {
+ let model = device.get_model();
+ let serial = device.get_serial_number()?;
+ Ok(Self {
+ pin_type,
+ model,
+ serial,
+ })
+ }
+
+ fn cache_id(&self) -> String {
+ let model = self.model.to_string().to_lowercase();
+ let suffix = format!("{}:{}", model, self.serial);
+
+ match self.pin_type {
+ PinType::Admin => format!("nitrocli:admin:{}", suffix),
+ PinType::User => format!("nitrocli:user:{}", suffix),
}
}
- fn prompt(self) -> &'static str {
- match self {
+ fn prompt(&self) -> &'static str {
+ match self.pin_type {
PinType::Admin => "Admin PIN",
PinType::User => "User PIN",
}
}
- fn description(self, mode: Mode) -> &'static str {
- match self {
- PinType::Admin => match mode {
- Mode::Choose => "Please enter a new admin PIN",
- Mode::Confirm => "Please confirm the new admin PIN",
- Mode::Query => "Please enter the admin PIN",
+ fn description(&self, mode: Mode) -> String {
+ format!(
+ "{} for\rNitrokey {} {}",
+ match self.pin_type {
+ PinType::Admin => match mode {
+ Mode::Choose => "Please enter a new admin PIN",
+ Mode::Confirm => "Please confirm the new admin PIN",
+ Mode::Query => "Please enter the admin PIN",
+ },
+ PinType::User => match mode {
+ Mode::Choose => "Please enter a new user PIN",
+ Mode::Confirm => "Please confirm the new user PIN",
+ Mode::Query => "Please enter the user PIN",
+ },
},
- PinType::User => match mode {
- Mode::Choose => "Please enter a new user PIN",
- Mode::Confirm => "Please confirm the new user PIN",
- Mode::Query => "Please enter the user PIN",
- },
- }
+ self.model,
+ self.serial,
+ )
+ }
+
+ pub fn pin_type(&self) -> PinType {
+ self.pin_type
}
}
@@ -134,18 +166,18 @@ where
/// description and to decide whether a quality bar is shown in the
/// dialog.
pub fn inquire_pin(
- pin_type: PinType,
+ pin_entry: &PinEntry,
mode: Mode,
error_msg: Option<&str>,
) -> Result<String, Error> {
- let cache_id = pin_type.cache_id();
+ let cache_id = pin_entry.cache_id();
let error_msg = error_msg
.map(|msg| msg.replace(" ", "+"))
.unwrap_or_else(|| String::from("+"));
- let prompt = pin_type.prompt().replace(" ", "+");
- let description = pin_type.description(mode).replace(" ", "+");
+ let prompt = pin_entry.prompt().replace(" ", "+");
+ let description = pin_entry.description(mode).replace(" ", "+");
- let args = vec![cache_id, &error_msg, &prompt, &description].join(" ");
+ let args = vec![cache_id, error_msg, prompt, description].join(" ");
let mut command = "GET_PASSPHRASE --data ".to_string();
if mode.show_quality_bar() {
command += "--qualitybar ";
@@ -178,9 +210,9 @@ where
Err(Error::Error(format!("Unexpected response: {}", string)))
}
-/// Clear the cached pin of the given type.
-pub fn clear_pin(pin_type: PinType) -> Result<(), Error> {
- let command = "CLEAR_PASSPHRASE ".to_string() + pin_type.cache_id();
+/// Clear the cached pin represented by the given entry.
+pub fn clear_pin(pin_entry: &PinEntry) -> Result<(), Error> {
+ let command = format!("CLEAR_PASSPHRASE {}", pin_entry.cache_id());
let output = process::Command::new("gpg-connect-agent")
.arg(command)
.arg("/bye")