diff options
Diffstat (limited to 'nitrocli/src/commands.rs')
-rw-r--r-- | nitrocli/src/commands.rs | 88 |
1 files changed, 52 insertions, 36 deletions
diff --git a/nitrocli/src/commands.rs b/nitrocli/src/commands.rs index 209fb8f..00a594f 100644 --- a/nitrocli/src/commands.rs +++ b/nitrocli/src/commands.rs @@ -81,13 +81,18 @@ fn get_storage_device(ctx: &mut args::ExecCtx<'_>) -> Result<nitrokey::Storage> } /// Open the password safe on the given device. -fn get_password_safe<'dev>( +fn get_password_safe<'dev, D>( ctx: &mut args::ExecCtx<'_>, - device: &'dev dyn Device, -) -> Result<nitrokey::PasswordSafe<'dev>> { + device: &'dev D, +) -> Result<nitrokey::PasswordSafe<'dev>> +where + D: Device, +{ + let pin_entry = pinentry::PinEntry::from(pinentry::PinType::User, device)?; + try_with_pin_and_data( ctx, - pinentry::PinType::User, + &pin_entry, "Could not access the password safe", (), |_, pin| device.get_password_safe(pin).map_err(|err| ((), err)), @@ -108,7 +113,9 @@ where D: Device, F: Fn(D, &str) -> result::Result<A, (D, nitrokey::CommandError)>, { - try_with_pin_and_data(ctx, pin_type, msg, device, op) + let pin_entry = pinentry::PinEntry::from(pin_type, &device)?; + + try_with_pin_and_data(ctx, &pin_entry, msg, device, op) } /// Authenticate the given device with the user PIN. @@ -167,7 +174,7 @@ fn get_volume_status(status: &nitrokey::VolumeStatus) -> &'static str { /// second or third try, it will call `op` with the data returned by the /// previous call to `op`. fn try_with_pin_and_data_with_pinentry<D, F, R>( - pin_type: pinentry::PinType, + pin_entry: &pinentry::PinEntry, msg: &'static str, data: D, op: F, @@ -179,12 +186,12 @@ where let mut retry = 3; let mut error_msg = None; loop { - let pin = pinentry::inquire_pin(pin_type, pinentry::Mode::Query, error_msg)?; + let pin = pinentry::inquire_pin(pin_entry, pinentry::Mode::Query, error_msg)?; match op(data, &pin) { Ok(result) => return Ok(result), Err((new_data, err)) => match err { nitrokey::CommandError::WrongPassword => { - pinentry::clear_pin(pin_type)?; + pinentry::clear_pin(pin_entry)?; retry -= 1; if retry > 0 { @@ -203,7 +210,7 @@ where /// Try to execute the given function with a PIN. fn try_with_pin_and_data<D, F, R>( ctx: &mut args::ExecCtx<'_>, - pin_type: pinentry::PinType, + pin_entry: &pinentry::PinEntry, msg: &'static str, data: D, op: F, @@ -211,7 +218,7 @@ fn try_with_pin_and_data<D, F, R>( where F: Fn(D, &str) -> result::Result<R, (D, nitrokey::CommandError)>, { - let pin = match pin_type { + let pin = match pin_entry.pin_type() { pinentry::PinType::Admin => &ctx.admin_pin, pinentry::PinType::User => &ctx.user_pin, }; @@ -225,7 +232,7 @@ where })?; op(data, &pin).map_err(|(_, err)| get_error(msg, err)) } else { - try_with_pin_and_data_with_pinentry(pin_type, msg, data, op) + try_with_pin_and_data_with_pinentry(pin_entry, msg, data, op) } } @@ -235,14 +242,14 @@ where /// it refrains from passing any data to it. fn try_with_pin<F>( ctx: &mut args::ExecCtx<'_>, - pin_type: pinentry::PinType, + pin_entry: &pinentry::PinEntry, msg: &'static str, op: F, ) -> Result<()> where F: Fn(&str) -> result::Result<(), nitrokey::CommandError>, { - try_with_pin_and_data(ctx, pin_type, msg, (), |data, pin| { + try_with_pin_and_data(ctx, pin_entry, msg, (), |data, pin| { op(pin).map_err(|err| (data, err)) }) } @@ -287,12 +294,11 @@ pub fn status(ctx: &mut args::ExecCtx<'_>) -> Result<()> { /// Open the encrypted volume on the nitrokey. pub fn storage_open(ctx: &mut args::ExecCtx<'_>) -> Result<()> { let device = get_storage_device(ctx)?; - try_with_pin( - ctx, - pinentry::PinType::User, - "Opening encrypted volume failed", - |pin| device.enable_encrypted_volume(&pin), - ) + let pin_entry = pinentry::PinEntry::from(pinentry::PinType::User, &device)?; + + try_with_pin(ctx, &pin_entry, "Opening encrypted volume failed", |pin| { + device.enable_encrypted_volume(&pin) + }) } /// Close the previously opened encrypted volume. @@ -573,9 +579,14 @@ pub fn otp_status(ctx: &mut args::ExecCtx<'_>, all: bool) -> Result<()> { } /// Clear the PIN stored by various operations. -pub fn pin_clear() -> Result<()> { - pinentry::clear_pin(pinentry::PinType::Admin)?; - pinentry::clear_pin(pinentry::PinType::User)?; +pub fn pin_clear(ctx: &mut args::ExecCtx<'_>) -> Result<()> { + let device = get_device(ctx)?; + + pinentry::clear_pin(&pinentry::PinEntry::from( + pinentry::PinType::Admin, + &device, + )?)?; + pinentry::clear_pin(&pinentry::PinEntry::from(pinentry::PinType::User, &device)?)?; Ok(()) } @@ -594,14 +605,14 @@ fn check_pin(pin_type: pinentry::PinType, pin: &str) -> Result<()> { } } -fn choose_pin_with_pinentry(pin_type: pinentry::PinType) -> Result<String> { - pinentry::clear_pin(pin_type)?; - let new_pin = pinentry::inquire_pin(pin_type, pinentry::Mode::Choose, None)?; - pinentry::clear_pin(pin_type)?; - check_pin(pin_type, &new_pin)?; +fn choose_pin_with_pinentry(pin_entry: &pinentry::PinEntry) -> Result<String> { + pinentry::clear_pin(pin_entry)?; + let new_pin = pinentry::inquire_pin(pin_entry, pinentry::Mode::Choose, None)?; + pinentry::clear_pin(pin_entry)?; + check_pin(pin_entry.pin_type(), &new_pin)?; - let confirm_pin = pinentry::inquire_pin(pin_type, pinentry::Mode::Confirm, None)?; - pinentry::clear_pin(pin_type)?; + let confirm_pin = pinentry::inquire_pin(pin_entry, pinentry::Mode::Confirm, None)?; + pinentry::clear_pin(pin_entry)?; if new_pin != confirm_pin { Err(Error::from("Entered PINs do not match")) @@ -616,10 +627,10 @@ fn choose_pin_with_pinentry(pin_type: pinentry::PinType) -> Result<String> { /// given PIN type, it will be used. fn choose_pin( ctx: &mut args::ExecCtx<'_>, - pin_type: pinentry::PinType, + pin_entry: &pinentry::PinEntry, new: bool, ) -> Result<String> { - let new_pin = match pin_type { + let new_pin = match pin_entry.pin_type() { pinentry::PinType::Admin => { if new { &ctx.new_admin_pin @@ -642,17 +653,19 @@ fn choose_pin( .ok_or_else(|| Error::from("Failed to read PIN: invalid Unicode data found")) .map(ToOwned::to_owned) } else { - choose_pin_with_pinentry(pin_type) + choose_pin_with_pinentry(pin_entry) } } /// Change a PIN. pub fn pin_set(ctx: &mut args::ExecCtx<'_>, pin_type: pinentry::PinType) -> Result<()> { let device = get_device(ctx)?; - let new_pin = choose_pin(ctx, pin_type, true)?; + let pin_entry = pinentry::PinEntry::from(pin_type, &device)?; + let new_pin = choose_pin(ctx, &pin_entry, true)?; + try_with_pin( ctx, - pin_type, + &pin_entry, "Could not change the PIN", |current_pin| match pin_type { pinentry::PinType::Admin => device.change_admin_pin(¤t_pin, &new_pin), @@ -664,10 +677,13 @@ pub fn pin_set(ctx: &mut args::ExecCtx<'_>, pin_type: pinentry::PinType) -> Resu /// Unblock and reset the user PIN. pub fn pin_unblock(ctx: &mut args::ExecCtx<'_>) -> Result<()> { let device = get_device(ctx)?; - let user_pin = choose_pin(ctx, pinentry::PinType::User, false)?; + let pin_entry = pinentry::PinEntry::from(pinentry::PinType::User, &device)?; + let user_pin = choose_pin(ctx, &pin_entry, false)?; + let pin_entry = pinentry::PinEntry::from(pinentry::PinType::Admin, &device)?; + try_with_pin( ctx, - pinentry::PinType::Admin, + &pin_entry, "Could not unblock the user PIN", |admin_pin| device.unlock_user_pin(&admin_pin, &user_pin), ) |