diff options
| -rw-r--r-- | nitrocli/src/commands.rs | 94 | ||||
| -rw-r--r-- | nitrocli/src/pinentry.rs | 40 | 
2 files changed, 66 insertions, 68 deletions
| diff --git a/nitrocli/src/commands.rs b/nitrocli/src/commands.rs index a5600b1..1d5c67c 100644 --- a/nitrocli/src/commands.rs +++ b/nitrocli/src/commands.rs @@ -91,15 +91,11 @@ fn get_storage_device(ctx: &mut args::ExecCtx<'_>) -> Result<nitrokey::Storage>  /// Open the password safe on the given device.  fn get_password_safe(device: &dyn Device) -> Result<nitrokey::PasswordSafe<'_>> { -  try_with_passphrase_and_data( +  try_with_pin_and_data(      pinentry::PinType::User,      "Could not access the password safe",      (), -    |_, passphrase| { -      device -        .get_password_safe(passphrase) -        .map_err(|err| ((), err)) -    }, +    |_, pin| device.get_password_safe(pin).map_err(|err| ((), err)),    )    .map_err(|(_, err)| err)  } @@ -117,7 +113,7 @@ where    D: Device,    F: Fn(D, &str) -> result::Result<A, (D, nitrokey::CommandError)>,  { -  try_with_passphrase_and_data(pin_type, msg, device, op).map_err(|(_device, err)| err) +  try_with_pin_and_data(pin_type, msg, device, op).map_err(|(_device, err)| err)  }  /// Authenticate the given device with the user PIN. @@ -129,7 +125,7 @@ where      device,      pinentry::PinType::User,      "Could not authenticate as user", -    |device, passphrase| device.authenticate_user(passphrase), +    |device, pin| device.authenticate_user(pin),    )  } @@ -142,7 +138,7 @@ where      device,      pinentry::PinType::Admin,      "Could not authenticate as admin", -    |device, passphrase| device.authenticate_admin(passphrase), +    |device, pin| device.authenticate_admin(pin),    )  } @@ -159,22 +155,22 @@ fn get_volume_status(status: &nitrokey::VolumeStatus) -> &'static str {    }  } -/// Try to execute the given function with a passphrase queried using pinentry. +/// Try to execute the given function with a pin queried using pinentry.  /// -/// This function will query the passphrase of the given type from the -/// user using pinentry.  It will then execute the given function.  If -/// this function returns a result, the result will be passed it on.  If -/// it returns a `CommandError::WrongPassword`, the user will be asked -/// again to enter the passphrase.  Otherwise, this function returns an -/// error containing the given error message.  The user will have at -/// most three tries to get the passphrase right. +/// This function will query the pin of the given type from the user +/// using pinentry.  It will then execute the given function.  If this +/// function returns a result, the result will be passed it on.  If it +/// returns a `CommandError::WrongPassword`, the user will be asked +/// again to enter the pin.  Otherwise, this function returns an error +/// containing the given error message.  The user will have at most +/// three tries to get the pin right.  ///  /// The data argument can be used to pass on data between the tries.  At  /// the first try, this function will call `op` with `data`.  At the  /// second or third try, it will call `op` with the data returned by the  /// previous call to `op`. -fn try_with_passphrase_and_data<D, F, R>( -  pin: pinentry::PinType, +fn try_with_pin_and_data<D, F, R>( +  pin_type: pinentry::PinType,    msg: &'static str,    data: D,    op: F, @@ -186,19 +182,19 @@ where    let mut retry = 3;    let mut error_msg = None;    loop { -    let passphrase = match pinentry::inquire_passphrase(pin, pinentry::Mode::Query, error_msg) { -      Ok(passphrase) => passphrase, +    let pin = match pinentry::inquire_pin(pin_type, pinentry::Mode::Query, error_msg) { +      Ok(pin) => pin,        Err(err) => return Err((data, err)),      }; -    let passphrase = match String::from_utf8(passphrase) { -      Ok(passphrase) => passphrase, +    let pin = match String::from_utf8(pin) { +      Ok(pin) => pin,        Err(err) => return Err((data, Error::from(err))),      }; -    match op(data, &passphrase) { +    match op(data, &pin) {        Ok(result) => return Ok(result),        Err((new_data, err)) => match err {          nitrokey::CommandError::WrongPassword => { -          if let Err(err) = pinentry::clear_passphrase(pin) { +          if let Err(err) = pinentry::clear_pin(pin_type) {              return Err((new_data, err));            }            retry -= 1; @@ -217,16 +213,16 @@ where    }  } -/// Try to execute the given function with a passphrase queried using pinentry. +/// Try to execute the given function with a pin queried using pinentry.  /// -/// This function behaves exactly as `try_with_passphrase_and_data`, but +/// This function behaves exactly as `try_with_pin_and_data`, but  /// it refrains from passing any data to it. -fn try_with_passphrase<F>(pin: pinentry::PinType, msg: &'static str, op: F) -> Result<()> +fn try_with_pin<F>(pin_type: pinentry::PinType, msg: &'static str, op: F) -> Result<()>  where    F: Fn(&str) -> result::Result<(), nitrokey::CommandError>,  { -  try_with_passphrase_and_data(pin, msg, (), |data, passphrase| { -    op(passphrase).map_err(|err| (data, err)) +  try_with_pin_and_data(pin_type, msg, (), |data, pin| { +    op(pin).map_err(|err| (data, err))    })    .map_err(|(_data, err)| err)  } @@ -271,10 +267,10 @@ 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_passphrase( +  try_with_pin(      pinentry::PinType::User,      "Opening encrypted volume failed", -    |passphrase| device.enable_encrypted_volume(&passphrase), +    |pin| device.enable_encrypted_volume(&pin),    )  } @@ -560,13 +556,13 @@ 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_passphrase(pinentry::PinType::Admin)?; -  pinentry::clear_passphrase(pinentry::PinType::User)?; +  pinentry::clear_pin(pinentry::PinType::Admin)?; +  pinentry::clear_pin(pinentry::PinType::User)?;    Ok(())  } -fn check_pin(pintype: pinentry::PinType, pin: &str) -> Result<()> { -  let minimum_length = match pintype { +fn check_pin(pin_type: pinentry::PinType, pin: &str) -> Result<()> { +  let minimum_length = match pin_type {      pinentry::PinType::Admin => 8,      pinentry::PinType::User => 6,    }; @@ -580,15 +576,15 @@ fn check_pin(pintype: pinentry::PinType, pin: &str) -> Result<()> {    }  } -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)?; +fn choose_pin(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)?;    let new_pin = String::from_utf8(new_pin)?; -  check_pin(pintype, &new_pin)?; +  check_pin(pin_type, &new_pin)?; -  let confirm_pin = pinentry::inquire_passphrase(pintype, pinentry::Mode::Confirm, None)?; -  pinentry::clear_passphrase(pintype)?; +  let confirm_pin = pinentry::inquire_pin(pin_type, pinentry::Mode::Confirm, None)?; +  pinentry::clear_pin(pin_type)?;    let confirm_pin = String::from_utf8(confirm_pin)?;    if new_pin != confirm_pin { @@ -599,13 +595,13 @@ fn choose_pin(pintype: pinentry::PinType) -> Result<String> {  }  /// Change a PIN. -pub fn pin_set(ctx: &mut args::ExecCtx<'_>, pintype: pinentry::PinType) -> Result<()> { +pub fn pin_set(ctx: &mut args::ExecCtx<'_>, pin_type: pinentry::PinType) -> Result<()> {    let device = get_device(ctx)?; -  let new_pin = choose_pin(pintype)?; -  try_with_passphrase( -    pintype, +  let new_pin = choose_pin(pin_type)?; +  try_with_pin( +    pin_type,      "Could not change the PIN", -    |current_pin| match pintype { +    |current_pin| match pin_type {        pinentry::PinType::Admin => device.change_admin_pin(¤t_pin, &new_pin),        pinentry::PinType::User => device.change_user_pin(¤t_pin, &new_pin),      }, @@ -616,7 +612,7 @@ pub fn pin_set(ctx: &mut args::ExecCtx<'_>, pintype: pinentry::PinType) -> Resul  pub fn pin_unblock(ctx: &mut args::ExecCtx<'_>) -> Result<()> {    let device = get_device(ctx)?;    let user_pin = choose_pin(pinentry::PinType::User)?; -  try_with_passphrase( +  try_with_pin(      pinentry::PinType::Admin,      "Could not unblock the user PIN",      |admin_pin| device.unlock_user_pin(&admin_pin, &user_pin), diff --git a/nitrocli/src/pinentry.rs b/nitrocli/src/pinentry.rs index 0d9fc5f..6c36d73 100644 --- a/nitrocli/src/pinentry.rs +++ b/nitrocli/src/pinentry.rs @@ -93,9 +93,9 @@ impl PinType {  /// PIN entry mode for pinentry.  /// -/// This enum describes the context of the pinentry query, for example prompting for the current -/// PIN or requesting a new PIN.  The mode may affect the pinentry description and whether a -/// quality bar is shown. +/// This enum describes the context of the pinentry query, for example +/// prompting for the current PIN or requesting a new PIN.  The mode may +/// affect the pinentry description and whether a quality bar is shown.  #[derive(Clone, Copy, Debug, PartialEq)]  pub enum Mode {    /// Let the user choose a new PIN. @@ -112,7 +112,7 @@ impl Mode {    }  } -fn parse_pinentry_passphrase(response: Vec<u8>) -> Result<Vec<u8>, Error> { +fn parse_pinentry_pin(response: Vec<u8>) -> Result<Vec<u8>, Error> {    let string = String::from_utf8(response)?;    let lines: Vec<&str> = string.lines().collect(); @@ -138,11 +138,13 @@ fn parse_pinentry_passphrase(response: Vec<u8>) -> Result<Vec<u8>, Error> {  /// Inquire a PIN of the given type from the user.  /// -/// This function inquires a PIN of the given type from the user or returns the cached passphrase, -/// if available.  If an error message is set, it is displayed in the passphrase dialog.  The -/// mode describes the context of the pinentry dialog.  It is used to choose an appropriate -/// description and to decide whether a quality bar is shown in the dialog. -pub fn inquire_passphrase( +/// This function inquires a PIN of the given type from the user or +/// returns the cached pin, if available.  If an error message is set, +/// it is displayed in the pin dialog.  The mode describes the context +/// of the pinentry dialog.  It is used to choose an appropriate +/// description and to decide whether a quality bar is shown in the +/// dialog. +pub fn inquire_pin(    pin_type: PinType,    mode: Mode,    error_msg: Option<&str>, @@ -161,7 +163,7 @@ pub fn inquire_passphrase(    }    command += &args;    // We could also use the --data parameter here to have a more direct -  // representation of the passphrase but the resulting response was +  // representation of the pin but the resulting response was    // considered more difficult to parse overall. It appears an error    // reported for the GET_PASSPHRASE command does not actually cause    // gpg-connect-agent to exit with a non-zero error code, we have to @@ -170,7 +172,7 @@ pub fn inquire_passphrase(      .arg(command)      .arg("/bye")      .output()?; -  parse_pinentry_passphrase(output.stdout) +  parse_pinentry_pin(output.stdout)  }  fn parse_pinentry_response(response: Vec<u8>) -> Result<(), Error> { @@ -184,8 +186,8 @@ fn parse_pinentry_response(response: Vec<u8>) -> Result<(), Error> {    Err(Error::Error("Unexpected response: ".to_string() + &string))  } -/// Clear the cached passphrase of the given type. -pub fn clear_passphrase(pin_type: PinType) -> Result<(), Error> { +/// 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();    let output = process::Command::new("gpg-connect-agent")      .arg(command) @@ -200,20 +202,20 @@ mod tests {    use super::*;    #[test] -  fn parse_pinentry_passphrase_good() { +  fn parse_pinentry_pin_good() {      let response = "D passphrase\nOK\n".to_string().into_bytes();      let expected = "passphrase".to_string().into_bytes(); -    assert_eq!(parse_pinentry_passphrase(response).unwrap(), expected) +    assert_eq!(parse_pinentry_pin(response).unwrap(), expected)    }    #[test] -  fn parse_pinentry_passphrase_error() { +  fn parse_pinentry_pin_error() {      let error = "83886179 Operation cancelled";      let response = "ERR ".to_string() + error + "\n";      let expected = error; -    let error = parse_pinentry_passphrase(response.to_string().into_bytes()); +    let error = parse_pinentry_pin(response.to_string().into_bytes());      if let Error::Error(ref e) = error.err().unwrap() {        assert_eq!(e, &expected); @@ -223,11 +225,11 @@ mod tests {    }    #[test] -  fn parse_pinentry_passphrase_unexpected() { +  fn parse_pinentry_pin_unexpected() {      let response = "foobar\n";      let expected = "Unexpected response: ".to_string() + response; -    let error = parse_pinentry_passphrase(response.to_string().into_bytes()); +    let error = parse_pinentry_pin(response.to_string().into_bytes());      if let Error::Error(ref e) = error.err().unwrap() {        assert_eq!(e, &expected); | 
