diff options
| -rw-r--r-- | nitrocli/src/args.rs | 67 | ||||
| -rw-r--r-- | nitrocli/src/commands.rs | 44 | 
2 files changed, 58 insertions, 53 deletions
| diff --git a/nitrocli/src/args.rs b/nitrocli/src/args.rs index b5d4e81..e45c4b9 100644 --- a/nitrocli/src/args.rs +++ b/nitrocli/src/args.rs @@ -63,9 +63,10 @@ impl str::FromStr for DeviceModel {  /// A command execution context that captures additional data pertaining  /// the command execution.  #[derive(Debug)] -pub struct ExecCtx { +pub struct ExecCtx<'io> {    pub model: Option<DeviceModel>,    pub verbosity: u64, +  data: std::marker::PhantomData<&'io u64>,  }  /// A top-level command for nitrocli. @@ -82,7 +83,7 @@ pub enum Command {  impl Command {    /// Execute this command with the given arguments. -  pub fn execute(&self, ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +  pub fn execute(&self, ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {      match *self {        Command::Config => config(ctx, args),        Command::Lock => lock(ctx, args), @@ -137,7 +138,7 @@ enum ConfigCommand {  }  impl ConfigCommand { -  fn execute(&self, ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +  fn execute(&self, ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {      match *self {        ConfigCommand::Get => config_get(ctx, args),        ConfigCommand::Set => config_set(ctx, args), @@ -214,7 +215,7 @@ enum OtpCommand {  }  impl OtpCommand { -  fn execute(&self, ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +  fn execute(&self, ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {      match *self {        OtpCommand::Clear => otp_clear(ctx, args),        OtpCommand::Get => otp_get(ctx, args), @@ -366,7 +367,7 @@ enum PinCommand {  }  impl PinCommand { -  fn execute(&self, ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +  fn execute(&self, ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {      match *self {        PinCommand::Clear => pin_clear(args),        PinCommand::Set => pin_set(ctx, args), @@ -411,7 +412,7 @@ enum PwsCommand {  }  impl PwsCommand { -  fn execute(&self, ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +  fn execute(&self, ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {      match *self {        PwsCommand::Clear => pws_clear(ctx, args),        PwsCommand::Get => pws_get(ctx, args), @@ -459,7 +460,7 @@ fn parse(parser: &argparse::ArgumentParser<'_>, args: Vec<String>) -> Result<()>  }  /// Inquire the status of the nitrokey. -fn status(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +fn status(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut parser = argparse::ArgumentParser::new();    parser.set_description("Prints the status of the connected Nitrokey device");    parse(&parser, args)?; @@ -475,7 +476,7 @@ enum StorageCommand {  }  impl StorageCommand { -  fn execute(&self, ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +  fn execute(&self, ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {      match *self {        StorageCommand::Close => storage_close(ctx, args),        StorageCommand::Open => storage_open(ctx, args), @@ -512,7 +513,7 @@ impl str::FromStr for StorageCommand {  }  /// Execute a storage subcommand. -fn storage(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +fn storage(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut subcommand = StorageCommand::Open;    let mut subargs = vec![];    let mut parser = argparse::ArgumentParser::new(); @@ -536,7 +537,7 @@ fn storage(ctx: &ExecCtx, args: Vec<String>) -> Result<()> {  }  /// Open the encrypted volume on the nitrokey. -fn storage_open(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +fn storage_open(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut parser = argparse::ArgumentParser::new();    parser.set_description("Opens the encrypted volume on a Nitrokey Storage");    parse(&parser, args)?; @@ -545,7 +546,7 @@ fn storage_open(ctx: &ExecCtx, args: Vec<String>) -> Result<()> {  }  /// Close the previously opened encrypted volume. -fn storage_close(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +fn storage_close(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut parser = argparse::ArgumentParser::new();    parser.set_description("Closes the encrypted volume on a Nitrokey Storage");    parse(&parser, args)?; @@ -554,7 +555,7 @@ fn storage_close(ctx: &ExecCtx, args: Vec<String>) -> Result<()> {  }  /// Print the status of the nitrokey's storage. -fn storage_status(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +fn storage_status(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut parser = argparse::ArgumentParser::new();    parser.set_description("Prints the status of the Nitrokey's storage");    parse(&parser, args)?; @@ -563,7 +564,7 @@ fn storage_status(ctx: &ExecCtx, args: Vec<String>) -> Result<()> {  }  /// Execute a config subcommand. -fn config(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +fn config(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut subcommand = ConfigCommand::Get;    let mut subargs = vec![];    let mut parser = argparse::ArgumentParser::new(); @@ -587,7 +588,7 @@ fn config(ctx: &ExecCtx, args: Vec<String>) -> Result<()> {  }  /// Read the Nitrokey configuration. -fn config_get(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +fn config_get(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut parser = argparse::ArgumentParser::new();    parser.set_description("Prints the Nitrokey configuration");    parse(&parser, args)?; @@ -596,7 +597,7 @@ fn config_get(ctx: &ExecCtx, args: Vec<String>) -> Result<()> {  }  /// Write the Nitrokey configuration. -fn config_set(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +fn config_set(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut numlock = None;    let mut no_numlock = false;    let mut capslock = None; @@ -664,7 +665,7 @@ fn config_set(ctx: &ExecCtx, args: Vec<String>) -> Result<()> {  }  /// Lock the Nitrokey. -fn lock(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +fn lock(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut parser = argparse::ArgumentParser::new();    parser.set_description("Locks the connected Nitrokey device");    parse(&parser, args)?; @@ -673,7 +674,7 @@ fn lock(ctx: &ExecCtx, args: Vec<String>) -> Result<()> {  }  /// Execute an OTP subcommand. -fn otp(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +fn otp(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut subcommand = OtpCommand::Get;    let mut subargs = vec![];    let mut parser = argparse::ArgumentParser::new(); @@ -697,7 +698,7 @@ fn otp(ctx: &ExecCtx, args: Vec<String>) -> Result<()> {  }  /// Generate a one-time password on the Nitrokey device. -fn otp_get(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +fn otp_get(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut slot: u8 = 0;    let mut algorithm = OtpAlgorithm::Totp;    let mut time: Option<u64> = None; @@ -725,7 +726,7 @@ fn otp_get(ctx: &ExecCtx, args: Vec<String>) -> Result<()> {  }  /// Configure a one-time password slot on the Nitrokey device. -pub fn otp_set(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +pub fn otp_set(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut slot: u8 = 0;    let mut algorithm = OtpAlgorithm::Totp;    let mut name = "".to_owned(); @@ -809,7 +810,7 @@ pub fn otp_set(ctx: &ExecCtx, args: Vec<String>) -> Result<()> {  }  /// Clear an OTP slot. -fn otp_clear(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +fn otp_clear(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut slot: u8 = 0;    let mut algorithm = OtpAlgorithm::Totp;    let mut parser = argparse::ArgumentParser::new(); @@ -831,7 +832,7 @@ fn otp_clear(ctx: &ExecCtx, args: Vec<String>) -> Result<()> {  }  /// Print the status of the OTP slots. -fn otp_status(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +fn otp_status(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut all = false;    let mut parser = argparse::ArgumentParser::new();    parser.set_description("Prints the status of the OTP slots"); @@ -847,7 +848,7 @@ fn otp_status(ctx: &ExecCtx, args: Vec<String>) -> Result<()> {  }  /// Execute a PIN subcommand. -fn pin(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +fn pin(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut subcommand = PinCommand::Clear;    let mut subargs = vec![];    let mut parser = argparse::ArgumentParser::new(); @@ -880,7 +881,7 @@ fn pin_clear(args: Vec<String>) -> Result<()> {  }  /// Change a PIN. -fn pin_set(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +fn pin_set(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut pintype = pinentry::PinType::User;    let mut parser = argparse::ArgumentParser::new();    parser.set_description("Changes a PIN"); @@ -896,7 +897,7 @@ fn pin_set(ctx: &ExecCtx, args: Vec<String>) -> Result<()> {  }  /// Unblock and reset the user PIN. -fn pin_unblock(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +fn pin_unblock(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut parser = argparse::ArgumentParser::new();    parser.set_description("Unblocks and resets the user PIN");    parse(&parser, args)?; @@ -905,7 +906,7 @@ fn pin_unblock(ctx: &ExecCtx, args: Vec<String>) -> Result<()> {  }  /// Execute a PWS subcommand. -fn pws(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +fn pws(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut subcommand = PwsCommand::Get;    let mut subargs = vec![];    let mut parser = argparse::ArgumentParser::new(); @@ -929,7 +930,7 @@ fn pws(ctx: &ExecCtx, args: Vec<String>) -> Result<()> {  }  /// Access a slot of the password safe on the Nitrokey. -fn pws_get(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +fn pws_get(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut slot: u8 = 0;    let mut name = false;    let mut login = false; @@ -969,7 +970,7 @@ fn pws_get(ctx: &ExecCtx, args: Vec<String>) -> Result<()> {  }  /// Set a slot of the password safe on the Nitrokey. -fn pws_set(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +fn pws_set(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut slot: u8 = 0;    let mut name = String::new();    let mut login = String::new(); @@ -1003,7 +1004,7 @@ fn pws_set(ctx: &ExecCtx, args: Vec<String>) -> Result<()> {  }  /// Clear a PWS slot. -fn pws_clear(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +fn pws_clear(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut slot: u8 = 0;    let mut parser = argparse::ArgumentParser::new();    parser.set_description("Clears a password safe slot"); @@ -1019,7 +1020,7 @@ fn pws_clear(ctx: &ExecCtx, args: Vec<String>) -> Result<()> {  }  /// Print the status of the PWS slots. -fn pws_status(ctx: &ExecCtx, args: Vec<String>) -> Result<()> { +fn pws_status(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {    let mut all = false;    let mut parser = argparse::ArgumentParser::new();    parser.set_description("Prints the status of the PWS slots"); @@ -1036,7 +1037,7 @@ fn pws_status(ctx: &ExecCtx, args: Vec<String>) -> Result<()> {  /// 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, ExecCtx, Vec<String>)> { +fn parse_arguments<'io>(args: Vec<String>) -> Result<(Command, ExecCtx<'io>, Vec<String>)> {    let mut model: Option<DeviceModel> = None;    let mut verbosity = 0;    let mut command = Command::Status; @@ -1069,12 +1070,12 @@ fn parse_arguments(args: Vec<String>) -> Result<(Command, ExecCtx, Vec<String>)>    subargs.insert(0, format!("nitrocli {}", command)); -  let ctx = ExecCtx { model, verbosity }; +  let ctx = ExecCtx { model, verbosity, data: Default::default() };    Ok((command, ctx, subargs))  }  /// Parse the command-line arguments and execute the selected command.  pub fn handle_arguments(args: Vec<String>) -> Result<()> { -  let (command, ctx, args) = parse_arguments(args)?; -  command.execute(&ctx, args) +  let (command, mut ctx, args) = parse_arguments(args)?; +  command.execute(&mut ctx, args)  } diff --git a/nitrocli/src/commands.rs b/nitrocli/src/commands.rs index 289c257..6c83c29 100644 --- a/nitrocli/src/commands.rs +++ b/nitrocli/src/commands.rs @@ -39,7 +39,7 @@ fn get_error(msg: &str, err: nitrokey::CommandError) -> Error {  }  /// Set `libnitrokey`'s log level based on the execution context's verbosity. -fn set_log_level(ctx: &args::ExecCtx) { +fn set_log_level(ctx: &mut args::ExecCtx<'_>) {    let log_lvl = match ctx.verbosity {      // The error log level is what libnitrokey uses by default. As such,      // there is no harm in us setting that as well when the user did not @@ -55,7 +55,7 @@ fn set_log_level(ctx: &args::ExecCtx) {  }  /// Connect to any Nitrokey device and return it. -fn get_device(ctx: &args::ExecCtx) -> Result<nitrokey::DeviceWrapper> { +fn get_device(ctx: &mut args::ExecCtx<'_>) -> Result<nitrokey::DeviceWrapper> {    set_log_level(ctx);    match ctx.model { @@ -71,7 +71,7 @@ fn get_device(ctx: &args::ExecCtx) -> Result<nitrokey::DeviceWrapper> {  }  /// Connect to a Nitrokey Storage device and return it. -fn get_storage_device(ctx: &args::ExecCtx) -> Result<nitrokey::Storage> { +fn get_storage_device(ctx: &mut args::ExecCtx<'_>) -> Result<nitrokey::Storage> {    set_log_level(ctx);    if let Some(model) = ctx.model { @@ -254,7 +254,7 @@ fn print_status(model: &'static str, device: &nitrokey::DeviceWrapper) -> Result  }  /// Inquire the status of the nitrokey. -pub fn status(ctx: &args::ExecCtx) -> Result<()> { +pub fn status(ctx: &mut args::ExecCtx<'_>) -> Result<()> {    let device = get_device(ctx)?;    let model = match device {      nitrokey::DeviceWrapper::Pro(_) => "Pro", @@ -264,7 +264,7 @@ pub fn status(ctx: &args::ExecCtx) -> Result<()> {  }  /// Open the encrypted volume on the nitrokey. -pub fn storage_open(ctx: &args::ExecCtx) -> Result<()> { +pub fn storage_open(ctx: &mut args::ExecCtx<'_>) -> Result<()> {    let device = get_storage_device(ctx)?;    try_with_passphrase(      pinentry::PinType::User, @@ -274,7 +274,7 @@ pub fn storage_open(ctx: &args::ExecCtx) -> Result<()> {  }  /// Close the previously opened encrypted volume. -pub fn storage_close(ctx: &args::ExecCtx) -> Result<()> { +pub fn storage_close(ctx: &mut args::ExecCtx<'_>) -> Result<()> {    // Flush all filesystem caches to disk. We are mostly interested in    // making sure that the encrypted volume on the nitrokey we are    // about to close is not closed while not all data was written to @@ -315,7 +315,7 @@ fn print_storage_status(status: &nitrokey::StorageStatus) {  }  /// Connect to and pretty print the status of a Nitrokey Storage. -pub fn storage_status(ctx: &args::ExecCtx) -> Result<()> { +pub fn storage_status(ctx: &mut args::ExecCtx<'_>) -> Result<()> {    let device = get_storage_device(ctx)?;    let status = device      .get_status() @@ -334,7 +334,7 @@ fn format_option<T: fmt::Display>(option: Option<T>) -> String {  }  /// Read the Nitrokey configuration. -pub fn config_get(ctx: &args::ExecCtx) -> Result<()> { +pub fn config_get(ctx: &mut args::ExecCtx<'_>) -> Result<()> {    let config = get_device(ctx)?      .get_config()      .map_err(|err| get_error("Could not get configuration", err))?; @@ -354,7 +354,7 @@ pub fn config_get(ctx: &args::ExecCtx) -> Result<()> {  /// Write the Nitrokey configuration.  pub fn config_set( -  ctx: &args::ExecCtx, +  ctx: &mut args::ExecCtx<'_>,    numlock: args::ConfigOption<u8>,    capslock: args::ConfigOption<u8>,    scrollock: args::ConfigOption<u8>, @@ -376,7 +376,7 @@ pub fn config_set(  }  /// Lock the Nitrokey device. -pub fn lock(ctx: &args::ExecCtx) -> Result<()> { +pub fn lock(ctx: &mut args::ExecCtx<'_>) -> Result<()> {    get_device(ctx)?      .lock()      .map_err(|err| get_error("Getting Storage status failed", err)) @@ -403,7 +403,7 @@ fn get_unix_timestamp() -> Result<u64> {  /// Generate a one-time password on the Nitrokey device.  pub fn otp_get( -  ctx: &args::ExecCtx, +  ctx: &mut args::ExecCtx<'_>,    slot: u8,    algorithm: args::OtpAlgorithm,    time: Option<u64>, @@ -466,7 +466,7 @@ fn prepare_base32_secret(secret: &str) -> Result<String> {  /// Configure a one-time password slot on the Nitrokey device.  pub fn otp_set( -  ctx: &args::ExecCtx, +  ctx: &mut args::ExecCtx<'_>,    data: nitrokey::OtpSlotData,    algorithm: args::OtpAlgorithm,    counter: u64, @@ -489,7 +489,11 @@ pub fn otp_set(  }  /// Clear an OTP slot. -pub fn otp_clear(ctx: &args::ExecCtx, slot: u8, algorithm: args::OtpAlgorithm) -> Result<()> { +pub fn otp_clear( +  ctx: &mut args::ExecCtx<'_>, +  slot: u8, +  algorithm: args::OtpAlgorithm, +) -> Result<()> {    let device = authenticate_admin(get_device(ctx)?)?;    match algorithm {      args::OtpAlgorithm::Hotp => device.erase_hotp_slot(slot), @@ -535,7 +539,7 @@ fn print_otp_status(  }  /// Print the status of the OTP slots. -pub fn otp_status(ctx: &args::ExecCtx, all: bool) -> Result<()> { +pub fn otp_status(ctx: &mut args::ExecCtx<'_>, all: bool) -> Result<()> {    let device = get_device(ctx)?;    println!("alg\tslot\tname");    print_otp_status(args::OtpAlgorithm::Hotp, &device, all)?; @@ -584,7 +588,7 @@ fn choose_pin(pintype: pinentry::PinType) -> Result<String> {  }  /// Change a PIN. -pub fn pin_set(ctx: &args::ExecCtx, pintype: pinentry::PinType) -> Result<()> { +pub fn pin_set(ctx: &mut args::ExecCtx<'_>, pintype: pinentry::PinType) -> Result<()> {    let device = get_device(ctx)?;    let new_pin = choose_pin(pintype)?;    try_with_passphrase( @@ -598,7 +602,7 @@ pub fn pin_set(ctx: &args::ExecCtx, pintype: pinentry::PinType) -> Result<()> {  }  /// Unblock and reset the user PIN. -pub fn pin_unblock(ctx: &args::ExecCtx) -> Result<()> { +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( @@ -624,7 +628,7 @@ fn print_pws_data(  /// Read a PWS slot.  pub fn pws_get( -  ctx: &args::ExecCtx, +  ctx: &mut args::ExecCtx<'_>,    slot: u8,    show_name: bool,    show_login: bool, @@ -648,7 +652,7 @@ pub fn pws_get(  /// Write a PWS slot.  pub fn pws_set( -  ctx: &args::ExecCtx, +  ctx: &mut args::ExecCtx<'_>,    slot: u8,    name: &str,    login: &str, @@ -662,7 +666,7 @@ pub fn pws_set(  }  /// Clear a PWS slot. -pub fn pws_clear(ctx: &args::ExecCtx, slot: u8) -> Result<()> { +pub fn pws_clear(ctx: &mut args::ExecCtx<'_>, slot: u8) -> Result<()> {    let device = get_device(ctx)?;    let pws = get_password_safe(&device)?;    pws @@ -687,7 +691,7 @@ fn print_pws_slot(pws: &nitrokey::PasswordSafe<'_>, slot: usize, programmed: boo  }  /// Print the status of all PWS slots. -pub fn pws_status(ctx: &args::ExecCtx, all: bool) -> Result<()> { +pub fn pws_status(ctx: &mut args::ExecCtx<'_>, all: bool) -> Result<()> {    let device = get_device(ctx)?;    let pws = get_password_safe(&device)?;    let slots = pws | 
