From d35cdf7f0a9822f73f4e1d18494350840de2a421 Mon Sep 17 00:00:00 2001 From: Daniel Mueller Date: Mon, 27 May 2019 08:09:48 -0700 Subject: Move storage status subcommand into status command In an attempt to rework the structure of the storage command to better accommodate future requirements for allowing to change the read-write state of the unencrypted volume (as well as potentially the encrypted one), this change removes the storage status subcommand and merges its output into the storage command. --- nitrocli/CHANGELOG.md | 6 +++ nitrocli/README.md | 19 ++++----- nitrocli/doc/nitrocli.1 | 9 ++--- nitrocli/doc/nitrocli.1.pdf | Bin 18096 -> 18107 bytes nitrocli/src/args.rs | 10 ----- nitrocli/src/commands.rs | 88 +++++++++++++++++++++--------------------- nitrocli/src/tests/status.rs | 30 +++++++++++++- nitrocli/src/tests/storage.rs | 37 ++++++++---------- 8 files changed, 106 insertions(+), 93 deletions(-) diff --git a/nitrocli/CHANGELOG.md b/nitrocli/CHANGELOG.md index 4376d84..aa40810 100644 --- a/nitrocli/CHANGELOG.md +++ b/nitrocli/CHANGELOG.md @@ -1,3 +1,9 @@ +Unreleased +---------- +- Removed `storage status` subcommand + - Moved its output into `status` command + + 0.2.4 ----- - Added the `reset` command to perform a factory reset diff --git a/nitrocli/README.md b/nitrocli/README.md index 515e06a..280e494 100644 --- a/nitrocli/README.md +++ b/nitrocli/README.md @@ -21,7 +21,6 @@ The following commands are currently supported: - storage: Work with the Nitrokey's storage. - open: Open the encrypted volume. The user PIN needs to be entered. - close: Close the encrypted volume. - - status: Print information about the Nitrokey's storage. - hidden: - create: Create a hidden volume. - open: Open a hidden volume with a password. @@ -59,16 +58,14 @@ Status: firmware version: 0.47 user retry count: 3 admin retry count: 3 - -$ nitrocli storage status -Status: - SD card ID: 0x05dcad1d - firmware: unlocked - storage keys: created - volumes: - unencrypted: active - encrypted: active - hidden: inactive + Storage: + SD card ID: 0x05dcad1d + firmware: unlocked + storage keys: created + volumes: + unencrypted: active + encrypted: active + hidden: inactive # Close it again. $ nitrocli storage close diff --git a/nitrocli/doc/nitrocli.1 b/nitrocli/doc/nitrocli.1 index 9029335..ee6ea11 100644 --- a/nitrocli/doc/nitrocli.1 +++ b/nitrocli/doc/nitrocli.1 @@ -34,7 +34,9 @@ Print the nitrocli version and exit. .TP .B nitrocli status Print the status of the connected Nitrokey device, including the stick serial -number, the firmware version, and the PIN retry count. +number, the firmware version, and the PIN retry count. If the device is a +Nitrokey Storage, also print storage related information including the SD card +serial number, the encryption status, and the status of the volumes. .TP .B nitrocli lock Lock the Nitrokey. @@ -69,11 +71,6 @@ The user PIN that is required to open the volume is queried using \fBnitrocli storage close Close the encrypted volume on the Nitrokey Storage. .TP -\fBnitrocli storage status -Print the status of the connected Nitrokey Storage device's storage. The -printed information includes the SD card serial number, the encryption -status, and the status of the volumes. -.TP \fBnitrocli storage hidden create \fIslot\fR \fIstart\fR \fIend\fR Create a new hidden volume inside the encrypted volume. \fIslot\fR must indicate one of the four available slots. \fIstart\fR and \fIend\fR represent, diff --git a/nitrocli/doc/nitrocli.1.pdf b/nitrocli/doc/nitrocli.1.pdf index fa4e4bc..2be0f02 100644 Binary files a/nitrocli/doc/nitrocli.1.pdf and b/nitrocli/doc/nitrocli.1.pdf differ diff --git a/nitrocli/src/args.rs b/nitrocli/src/args.rs index 10a097e..0b0429a 100644 --- a/nitrocli/src/args.rs +++ b/nitrocli/src/args.rs @@ -250,7 +250,6 @@ Enum! {StorageCommand, [ Close => ("close", storage_close), Hidden => ("hidden", storage_hidden), Open => ("open", storage_open), - Status => ("status", storage_status), ]} /// Execute a storage subcommand. @@ -295,15 +294,6 @@ fn storage_close(ctx: &mut ExecCtx<'_>, args: Vec) -> Result<()> { commands::storage_close(ctx) } -/// Print the status of the nitrokey's storage. -fn storage_status(ctx: &mut ExecCtx<'_>, args: Vec) -> Result<()> { - let mut parser = argparse::ArgumentParser::new(); - parser.set_description("Prints the status of the Nitrokey's storage"); - parse(ctx, parser, args)?; - - commands::storage_status(ctx) -} - Enum! {HiddenCommand, [ Close => ("close", storage_hidden_close), Create => ("create", storage_hidden_create), diff --git a/nitrocli/src/commands.rs b/nitrocli/src/commands.rs index 7bb314c..d1ded11 100644 --- a/nitrocli/src/commands.rs +++ b/nitrocli/src/commands.rs @@ -258,6 +258,39 @@ where }) } +/// Pretty print the status of a Nitrokey Storage. +fn print_storage_status( + ctx: &mut args::ExecCtx<'_>, + status: &nitrokey::StorageStatus, +) -> Result<()> { + println!( + ctx, + r#" Storage: + SD card ID: {id:#x} + firmware: {fw} + storage keys: {sk} + volumes: + unencrypted: {vu} + encrypted: {ve} + hidden: {vh}"#, + id = status.serial_number_sd_card, + fw = if status.firmware_locked { + "locked" + } else { + "unlocked" + }, + sk = if status.stick_initialized { + "created" + } else { + "not created" + }, + vu = get_volume_status(&status.unencrypted_volume), + ve = get_volume_status(&status.encrypted_volume), + vh = get_volume_status(&status.hidden_volume), + )?; + Ok(()) +} + /// Query and pretty print the status that is common to all Nitrokey devices. fn print_status( ctx: &mut args::ExecCtx<'_>, @@ -267,6 +300,7 @@ fn print_status( let serial_number = device .get_serial_number() .map_err(|err| get_error("Could not query the serial number", err))?; + println!( ctx, r#"Status: @@ -282,7 +316,16 @@ fn print_status( urc = device.get_user_retry_count(), arc = device.get_admin_retry_count(), )?; - Ok(()) + + if let nitrokey::DeviceWrapper::Storage(device) = device { + let status = device + .get_status() + .map_err(|err| get_error("Getting Storage status failed", err))?; + + print_storage_status(ctx, &status) + } else { + Ok(()) + } } /// Inquire the status of the nitrokey. @@ -399,49 +442,6 @@ pub fn storage_hidden_close(ctx: &mut args::ExecCtx<'_>) -> Result<()> { .map_err(|err| get_error("Closing hidden volume failed", err)) } -/// Pretty print the status of a Nitrokey Storage. -fn print_storage_status( - ctx: &mut args::ExecCtx<'_>, - status: &nitrokey::StorageStatus, -) -> Result<()> { - println!( - ctx, - r#"Status: - SD card ID: {id:#x} - firmware: {fw} - storage keys: {sk} - volumes: - unencrypted: {vu} - encrypted: {ve} - hidden: {vh}"#, - id = status.serial_number_sd_card, - fw = if status.firmware_locked { - "locked" - } else { - "unlocked" - }, - sk = if status.stick_initialized { - "created" - } else { - "not created" - }, - vu = get_volume_status(&status.unencrypted_volume), - ve = get_volume_status(&status.encrypted_volume), - vh = get_volume_status(&status.hidden_volume), - )?; - Ok(()) -} - -/// Connect to and pretty print the status of a Nitrokey Storage. -pub fn storage_status(ctx: &mut args::ExecCtx<'_>) -> Result<()> { - let device = get_storage_device(ctx)?; - let status = device - .get_status() - .map_err(|err| get_error("Getting Storage status failed", err))?; - - print_storage_status(ctx, &status) -} - /// Return a String representation of the given Option. fn format_option(option: Option) -> String { match option { diff --git a/nitrocli/src/tests/status.rs b/nitrocli/src/tests/status.rs index 83ce61f..7aac5ad 100644 --- a/nitrocli/src/tests/status.rs +++ b/nitrocli/src/tests/status.rs @@ -37,10 +37,10 @@ fn not_found() { } #[test_device] -fn output(device: nitrokey::DeviceWrapper) -> crate::Result<()> { +fn output_pro(device: nitrokey::Pro) -> crate::Result<()> { let re = regex::Regex::new( r#"^Status: - model: (Pro|Storage) + model: Pro serial number: 0x[[:xdigit:]]{8} firmware version: \d+\.\d+ user retry count: [0-3] @@ -53,3 +53,29 @@ $"#, assert!(re.is_match(&out), out); Ok(()) } + +#[test_device] +fn output_storage(device: nitrokey::Storage) -> crate::Result<()> { + let re = regex::Regex::new( + r#"^Status: + model: Storage + serial number: 0x[[:xdigit:]]{8} + firmware version: \d+\.\d+ + user retry count: [0-3] + admin retry count: [0-3] + Storage: + SD card ID: 0x[[:xdigit:]]{8} + firmware: (un)?locked + storage keys: (not )?created + volumes: + unencrypted: (read-only|active|inactive) + encrypted: (read-only|active|inactive) + hidden: (read-only|active|inactive) +$"#, + ) + .unwrap(); + + let out = Nitrocli::with_dev(device).handle(&["status"])?; + assert!(re.is_match(&out), out); + Ok(()) +} diff --git a/nitrocli/src/tests/storage.rs b/nitrocli/src/tests/storage.rs index be933ca..5b45bdc 100644 --- a/nitrocli/src/tests/storage.rs +++ b/nitrocli/src/tests/storage.rs @@ -19,15 +19,6 @@ use super::*; -#[test_device] -fn status_on_pro(device: nitrokey::Pro) { - let res = Nitrocli::with_dev(device).handle(&["storage", "status"]); - assert_eq!( - res.unwrap_str_err(), - "This command is only available on the Nitrokey Storage", - ); -} - #[test_device] fn status_open_close(device: nitrokey::Storage) -> crate::Result<()> { fn make_re(open: Option) -> regex::Regex { @@ -42,14 +33,11 @@ fn status_open_close(device: nitrokey::Storage) -> crate::Result<()> { None => "(read-only|active|inactive)", }; let re = format!( - r#"^Status: - SD card ID: 0x[[:xdigit:]]{{8}} - firmware: (un)?locked - storage keys: (not )?created - volumes: - unencrypted: (read-only|active|inactive) - encrypted: {} - hidden: (read-only|active|inactive) + r#" + volumes: + unencrypted: (read-only|active|inactive) + encrypted: {} + hidden: (read-only|active|inactive) $"#, encrypted ); @@ -57,20 +45,29 @@ $"#, } let mut ncli = Nitrocli::with_dev(device); - let out = ncli.handle(&["storage", "status"])?; + let out = ncli.handle(&["status"])?; assert!(make_re(None).is_match(&out), out); let _ = ncli.handle(&["storage", "open"])?; - let out = ncli.handle(&["storage", "status"])?; + let out = ncli.handle(&["status"])?; assert!(make_re(Some(true)).is_match(&out), out); let _ = ncli.handle(&["storage", "close"])?; - let out = ncli.handle(&["storage", "status"])?; + let out = ncli.handle(&["status"])?; assert!(make_re(Some(false)).is_match(&out), out); Ok(()) } +#[test_device] +fn encrypted_open_on_pro(device: nitrokey::Pro) { + let res = Nitrocli::with_dev(device).handle(&["storage", "open"]); + assert_eq!( + res.unwrap_str_err(), + "This command is only available on the Nitrokey Storage", + ); +} + #[test_device] fn encrypted_open_close(device: nitrokey::Storage) -> crate::Result<()> { let mut ncli = Nitrocli::with_dev(device); -- cgit v1.2.1