aboutsummaryrefslogtreecommitdiff
path: root/nitrocli/src
diff options
context:
space:
mode:
Diffstat (limited to 'nitrocli/src')
-rw-r--r--nitrocli/src/args.rs15
-rw-r--r--nitrocli/src/commands.rs44
-rw-r--r--nitrocli/src/pinentry.rs10
3 files changed, 67 insertions, 2 deletions
diff --git a/nitrocli/src/args.rs b/nitrocli/src/args.rs
index edfd811..4341235 100644
--- a/nitrocli/src/args.rs
+++ b/nitrocli/src/args.rs
@@ -278,12 +278,14 @@ impl From<OtpMode> for nitrokey::OtpMode {
#[derive(Debug)]
enum PinCommand {
Clear,
+ Unblock,
}
impl PinCommand {
fn execute(&self, args: Vec<String>) -> Result<()> {
match *self {
PinCommand::Clear => pin_clear(args),
+ PinCommand::Unblock => pin_unblock(args),
}
}
}
@@ -295,6 +297,7 @@ impl fmt::Display for PinCommand {
"{}",
match *self {
PinCommand::Clear => "clear",
+ PinCommand::Unblock => "unblock",
}
)
}
@@ -306,6 +309,7 @@ impl str::FromStr for PinCommand {
fn from_str(s: &str) -> result::Result<Self, Self::Err> {
match s {
"clear" => Ok(PinCommand::Clear),
+ "unblock" => Ok(PinCommand::Unblock),
_ => Err(()),
}
}
@@ -689,7 +693,7 @@ fn pin(args: Vec<String>) -> Result<()> {
let _ = parser.refer(&mut subcommand).required().add_argument(
"subcommand",
argparse::Store,
- "The subcommand to execute (clear)",
+ "The subcommand to execute (clear|unblock)",
);
let _ = parser.refer(&mut subargs).add_argument(
"arguments",
@@ -713,6 +717,15 @@ fn pin_clear(args: Vec<String>) -> Result<()> {
commands::pin_clear()
}
+/// Unblock and reset the user PIN.
+fn pin_unblock(args: Vec<String>) -> Result<()> {
+ let mut parser = argparse::ArgumentParser::new();
+ parser.set_description("Unblocks and resets the user PIN");
+ parse(&parser, args)?;
+
+ commands::pin_unblock()
+}
+
/// Parse the command-line arguments and return the selected command and
/// the remaining arguments for the command.
fn parse_arguments(args: Vec<String>) -> Result<(Command, Vec<String>)> {
diff --git a/nitrocli/src/commands.rs b/nitrocli/src/commands.rs
index 7f25415..e3e2a14 100644
--- a/nitrocli/src/commands.rs
+++ b/nitrocli/src/commands.rs
@@ -474,6 +474,50 @@ pub fn pin_clear() -> Result<()> {
Ok(())
}
+fn check_pin(pintype: pinentry::PinType, pin: &str) -> Result<()> {
+ let minimum_length = match pintype {
+ pinentry::PinType::Admin => 8,
+ pinentry::PinType::User => 6,
+ };
+ if pin.len() < minimum_length {
+ Err(Error::Error(format!(
+ "The PIN must be at least {} characters long",
+ minimum_length
+ )))
+ } else {
+ Ok(())
+ }
+}
+
+fn choose_pin(pintype: pinentry::PinType) -> Result<String> {
+ pinentry::clear_passphrase(pintype)?;
+ let new_pin = pinentry::inquire_passphrase(pintype, pinentry::Mode::Choose, None)?;
+ pinentry::clear_passphrase(pintype)?;
+ let new_pin = String::from_utf8(new_pin)?;
+ check_pin(pintype, &new_pin)?;
+
+ let confirm_pin = pinentry::inquire_passphrase(pintype, pinentry::Mode::Confirm, None)?;
+ pinentry::clear_passphrase(pintype)?;
+ let confirm_pin = String::from_utf8(confirm_pin)?;
+
+ if new_pin != confirm_pin {
+ Err(Error::Error("Entered PINs do not match".to_string()))
+ } else {
+ Ok(new_pin)
+ }
+}
+
+/// Unblock and reset the user PIN.
+pub fn pin_unblock() -> Result<()> {
+ let device = get_device()?;
+ let user_pin = choose_pin(pinentry::PinType::User)?;
+ try_with_passphrase(
+ pinentry::PinType::Admin,
+ "Could not unblock the user PIN",
+ |admin_pin| device.unlock_user_pin(&admin_pin, &user_pin),
+ )
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/nitrocli/src/pinentry.rs b/nitrocli/src/pinentry.rs
index 90986be..33b5266 100644
--- a/nitrocli/src/pinentry.rs
+++ b/nitrocli/src/pinentry.rs
@@ -51,9 +51,13 @@ impl PinType {
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",
},
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",
},
}
@@ -67,13 +71,17 @@ impl PinType {
/// quality bar is shown.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Mode {
+ /// Let the user choose a new PIN.
+ Choose,
+ /// Let the user confirm the previously chosen PIN.
+ Confirm,
/// Query an existing PIN.
Query,
}
impl Mode {
fn show_quality_bar(self) -> bool {
- false
+ self == Mode::Choose
}
}