diff options
author | Robin Krahl <robin.krahl@ireas.org> | 2018-12-27 16:56:23 +0100 |
---|---|---|
committer | Daniel Mueller <deso@posteo.net> | 2019-01-07 18:13:35 -0800 |
commit | b6f322a99f5c864868ad1450bfeb342e7dae3222 (patch) | |
tree | 5d567f28fd5a29d3ca6f5721de0fefdf8458c9c9 | |
parent | c8db48074625680030fd8364097cc1a68f852b9d (diff) | |
download | nitrocli-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.rs | 44 | ||||
-rw-r--r-- | nitrocli/src/commands.rs | 52 |
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::*; |