diff options
| -rw-r--r-- | nitrocli/CHANGELOG.md | 2 | ||||
| -rw-r--r-- | nitrocli/doc/nitrocli.1 | 11 | ||||
| -rw-r--r-- | nitrocli/doc/nitrocli.1.pdf | bin | 13820 -> 14041 bytes | |||
| -rw-r--r-- | nitrocli/src/args.rs | 41 | ||||
| -rw-r--r-- | nitrocli/src/commands.rs | 19 | 
5 files changed, 68 insertions, 5 deletions
| diff --git a/nitrocli/CHANGELOG.md b/nitrocli/CHANGELOG.md index e6a4480..41cfd91 100644 --- a/nitrocli/CHANGELOG.md +++ b/nitrocli/CHANGELOG.md @@ -1,6 +1,8 @@  Unreleased  ----------  - Added the `-v`/`--verbose` option to control libnitrokey log level +- Added the `-m`/`--model` option to restrict connections to a device +  model  0.2.1 diff --git a/nitrocli/doc/nitrocli.1 b/nitrocli/doc/nitrocli.1 index 7786fc1..e4dbf10 100644 --- a/nitrocli/doc/nitrocli.1 +++ b/nitrocli/doc/nitrocli.1 @@ -3,7 +3,7 @@  nitrocli \- access Nitrokey devices  .SH SYNOPSIS  .B nitrocli -\fR[\fB\-v\fR|\fB\-\-verbose\fR] +[\fB\-m\fR|\fB\-\-model pro\fR|\fBstorage\fR] \fR[\fB\-v\fR|\fB\-\-verbose\fR]  \fIcommand\fR  [\fIarguments\fR]  .SH DESCRIPTION @@ -13,7 +13,12 @@ It can be used to access the encrypted volume, the one-time password generator,  and the password safe.  .SH OPTIONS  .TP -.B \-v, \-\-verbose +\fB\-m\fR, \fB\-\-model pro\fR|\fBstorage\fR +Restrict connections to the given device model. +If this option is not set, nitrocli will connect to any connected Nitrokey Pro +or Nitrokey Storage device. +.TP +\fB\-v\fR, \fB\-\-verbose\fR  Enable additional logging and control its verbosity. Logging enabled through  this option will appear on the standard error stream. This option can be  supplied multiple times. A single occurrence will show additional warnings. @@ -76,7 +81,7 @@ This command might require the user PIN (see the Configuration section).  .TP  \fBnitrocli otp set \fIslot name secret \  \fR[\fB\-a\fR|\fB\-\-algorithm \fIalgorithm\fR] \ -[\fB\-d\fR|\fB\-\-digits \fI digits\fR] [\fB\-c\fR|\fB\-\-counter \fIcounter\fR] \ +[\fB\-d\fR|\fB\-\-digits \fIdigits\fR] [\fB\-c\fR|\fB\-\-counter \fIcounter\fR] \  [\fB\-t\fR|\fB\-\-time-window \fItime window\fR] [\fB\-\-ascii\fR]  Configure a one-time password slot.  \fIslot\fR is the number of the slot to configure. diff --git a/nitrocli/doc/nitrocli.1.pdf b/nitrocli/doc/nitrocli.1.pdfBinary files differ index c5e8898..5127435 100644 --- a/nitrocli/doc/nitrocli.1.pdf +++ b/nitrocli/doc/nitrocli.1.pdf diff --git a/nitrocli/src/args.rs b/nitrocli/src/args.rs index 869734c..ad296c2 100644 --- a/nitrocli/src/args.rs +++ b/nitrocli/src/args.rs @@ -28,10 +28,43 @@ use crate::pinentry;  type Result<T> = result::Result<T, Error>; +/// The available Nitrokey models. +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum DeviceModel { +  Pro, +  Storage, +} + +impl fmt::Display for DeviceModel { +  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +    write!( +      f, +      "{}", +      match *self { +        DeviceModel::Pro => "pro", +        DeviceModel::Storage => "storage", +      } +    ) +  } +} + +impl str::FromStr for DeviceModel { +  type Err = (); + +  fn from_str(s: &str) -> result::Result<Self, Self::Err> { +    match s { +      "pro" => Ok(DeviceModel::Pro), +      "storage" => Ok(DeviceModel::Storage), +      _ => Err(()), +    } +  } +} +  /// A command execution context that captures additional data pertaining  /// the command execution.  #[derive(Debug)]  pub struct ExecCtx { +  pub model: Option<DeviceModel>,    pub verbosity: u64,  } @@ -952,6 +985,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>)> { +  let mut model: Option<DeviceModel> = None;    let mut verbosity = 0;    let mut command = Command::Status;    let mut subargs = vec![]; @@ -961,6 +995,11 @@ fn parse_arguments(args: Vec<String>) -> Result<(Command, ExecCtx, Vec<String>)>      argparse::IncrBy::<u64>(1),      "Increase the log level (can be supplied multiple times)",    ); +  let _ = parser.refer(&mut model).add_option( +    &["-m", "--model"], +    argparse::StoreOption, +    "Select the device model to connect to (pro|storage)", +  );    parser.set_description("Provides access to a Nitrokey device");    let _ = parser.refer(&mut command).required().add_argument(      "command", @@ -978,7 +1017,7 @@ fn parse_arguments(args: Vec<String>) -> Result<(Command, ExecCtx, Vec<String>)>    subargs.insert(0, format!("nitrocli {}", command)); -  let ctx = ExecCtx { verbosity }; +  let ctx = ExecCtx { model, verbosity };    Ok((command, ctx, subargs))  } diff --git a/nitrocli/src/commands.rs b/nitrocli/src/commands.rs index 27faf05..e125f17 100644 --- a/nitrocli/src/commands.rs +++ b/nitrocli/src/commands.rs @@ -58,13 +58,30 @@ fn set_log_level(ctx: &args::ExecCtx) {  fn get_device(ctx: &args::ExecCtx) -> Result<nitrokey::DeviceWrapper> {    set_log_level(ctx); -  nitrokey::connect().map_err(|_| Error::Error("Nitrokey device not found".to_string())) +  match ctx.model { +    Some(model) => match model { +      args::DeviceModel::Pro => nitrokey::Pro::connect().map(nitrokey::DeviceWrapper::Pro), +      args::DeviceModel::Storage => { +        nitrokey::Storage::connect().map(nitrokey::DeviceWrapper::Storage) +      } +    }, +    None => nitrokey::connect(), +  } +  .map_err(|_| Error::Error("Nitrokey device not found".to_string()))  }  /// Connect to a Nitrokey Storage device and return it.  fn get_storage_device(ctx: &args::ExecCtx) -> Result<nitrokey::Storage> {    set_log_level(ctx); +  if let Some(model) = ctx.model { +    if model != args::DeviceModel::Storage { +      return Err(Error::Error( +        "This command is only available on the Nitrokey Storage".to_string(), +      )); +    } +  } +    nitrokey::Storage::connect().or_else(|_| {      Err(Error::Error(        "Nitrokey Storage device not found".to_string(), | 
