aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Krahl <robin.krahl@ireas.org>2018-12-27 16:56:23 +0100
committerDaniel Mueller <deso@posteo.net>2019-01-07 18:13:35 -0800
commitb6f322a99f5c864868ad1450bfeb342e7dae3222 (patch)
tree5d567f28fd5a29d3ca6f5721de0fefdf8458c9c9
parentc8db48074625680030fd8364097cc1a68f852b9d (diff)
downloadnitrocli-b6f322a99f5c864868ad1450bfeb342e7dae3222.tar.gz
nitrocli-b6f322a99f5c864868ad1450bfeb342e7dae3222.tar.bz2
Implement the pws get subcommand
This patch implements the pws get subcommand that provides read access to a slot of the password safe. Per default, all available information – slot name, login and password – are printed. If one or more of the options --name, --login and --password are set, only the selected fields are printed. If --quiet is set, the field description is omitted such that the output can be easily parsed by other applications.
-rw-r--r--nitrocli/src/args.rs44
-rw-r--r--nitrocli/src/commands.rs52
2 files changed, 94 insertions, 2 deletions
diff --git a/nitrocli/src/args.rs b/nitrocli/src/args.rs
index df7f56c..1a54c43 100644
--- a/nitrocli/src/args.rs
+++ b/nitrocli/src/args.rs
@@ -330,9 +330,9 @@ enum PwsCommand {
}
impl PwsCommand {
- fn execute(&self, _args: Vec<String>) -> Result<()> {
+ fn execute(&self, args: Vec<String>) -> Result<()> {
match *self {
- PwsCommand::Get => Err(Error::Error("Not implemented".to_string())),
+ PwsCommand::Get => pws_get(args),
}
}
}
@@ -811,6 +811,46 @@ fn pws(args: Vec<String>) -> Result<()> {
subcommand.execute(subargs)
}
+/// Access a slot of the password safe on the Nitrokey.
+fn pws_get(args: Vec<String>) -> Result<()> {
+ let mut slot: u8 = 0;
+ let mut name = false;
+ let mut login = false;
+ let mut password = false;
+ let mut quiet = false;
+ let mut parser = argparse::ArgumentParser::new();
+ parser.set_description("Reads a password safe slot");
+ let _ = parser.refer(&mut slot).required().add_argument(
+ "slot",
+ argparse::Store,
+ "The PWS slot to read",
+ );
+ let _ = parser.refer(&mut name).add_option(
+ &["-n", "--name"],
+ argparse::StoreTrue,
+ "Show the name stored on the slot",
+ );
+ let _ = parser.refer(&mut login).add_option(
+ &["-l", "--login"],
+ argparse::StoreTrue,
+ "Show the login stored on the slot",
+ );
+ let _ = parser.refer(&mut password).add_option(
+ &["-p", "--password"],
+ argparse::StoreTrue,
+ "Show the password stored on the slot",
+ );
+ let _ = parser.refer(&mut quiet).add_option(
+ &["-q", "--quiet"],
+ argparse::StoreTrue,
+ "Print the stored data without description",
+ );
+ parse(&parser, args)?;
+ drop(parser);
+
+ commands::pws_get(slot, name, login, password, quiet)
+}
+
/// 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 b018a58..125b344 100644
--- a/nitrocli/src/commands.rs
+++ b/nitrocli/src/commands.rs
@@ -49,6 +49,21 @@ fn get_storage_device() -> 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(
+ pinentry::PinType::User,
+ "Could not access the password safe",
+ (),
+ |_, passphrase| {
+ device
+ .get_password_safe(passphrase)
+ .map_err(|err| ((), err))
+ },
+ )
+ .map_err(|(_, err)| err)
+}
+
/// Authenticate the given device using the given PIN type and operation.
///
/// If an error occurs, the error message `msg` is used.
@@ -532,6 +547,43 @@ pub fn pin_unblock() -> Result<()> {
)
}
+fn print_pws_data(
+ description: &'static str,
+ result: result::Result<String, nitrokey::CommandError>,
+ quiet: bool,
+) -> Result<()> {
+ let value = result.map_err(|err| get_error("Could not access PWS slot", &err))?;
+ if quiet {
+ println!("{}", value);
+ } else {
+ println!("{} {}", description, value);
+ }
+ Ok(())
+}
+
+/// Read a PWS slot.
+pub fn pws_get(
+ slot: u8,
+ show_name: bool,
+ show_login: bool,
+ show_password: bool,
+ quiet: bool,
+) -> Result<()> {
+ let device = get_device()?;
+ let pws = get_password_safe(&device)?;
+ let show_all = !show_name && !show_login && !show_password;
+ if show_all || show_name {
+ print_pws_data("name: ", pws.get_slot_name(slot), quiet)?;
+ }
+ if show_all || show_login {
+ print_pws_data("login: ", pws.get_slot_login(slot), quiet)?;
+ }
+ if show_all || show_password {
+ print_pws_data("password:", pws.get_slot_password(slot), quiet)?;
+ }
+ Ok(())
+}
+
#[cfg(test)]
mod tests {
use super::*;