From 37f7800766fe12af43d0cdba13aea9545cbe7755 Mon Sep 17 00:00:00 2001 From: Daniel Mueller Date: Sun, 20 Jan 2019 13:56:48 -0800 Subject: Add test for storage hidden subcommand This change adds a test for the creation, opening, and closing of a hidden subvolume. In order to support that in a non-interactive fashion, we introduce and honor the NITROCLI_PASSWORD environment variable, that prevents an interactive password query. --- nitrocli/src/args.rs | 2 ++ nitrocli/src/commands.rs | 18 ++++++++++++++++-- nitrocli/src/main.rs | 4 ++++ nitrocli/src/tests/mod.rs | 4 ++++ nitrocli/src/tests/storage.rs | 24 ++++++++++++++++++++++++ 5 files changed, 50 insertions(+), 2 deletions(-) (limited to 'nitrocli') diff --git a/nitrocli/src/args.rs b/nitrocli/src/args.rs index 0f4ef4f..0fed3be 100644 --- a/nitrocli/src/args.rs +++ b/nitrocli/src/args.rs @@ -49,6 +49,7 @@ pub struct ExecCtx<'io> { pub user_pin: Option, pub new_admin_pin: Option, pub new_user_pin: Option, + pub password: Option, pub verbosity: u64, } @@ -876,6 +877,7 @@ fn parse_arguments<'io, 'ctx: 'io>( user_pin: ctx.user_pin.take(), new_admin_pin: ctx.new_admin_pin.take(), new_user_pin: ctx.new_user_pin.take(), + password: ctx.password.take(), verbosity, }; Ok((command, ctx, subargs)) diff --git a/nitrocli/src/commands.rs b/nitrocli/src/commands.rs index ab70e29..989abbf 100644 --- a/nitrocli/src/commands.rs +++ b/nitrocli/src/commands.rs @@ -327,7 +327,14 @@ pub fn storage_hidden_create( ) -> Result<()> { let device = get_storage_device(ctx)?; let pwd_entry = pinentry::PwdEntry::from(&device)?; - let pwd = pinentry::choose(&pwd_entry)?; + let pwd = if let Some(pwd) = &ctx.password { + pwd + .to_str() + .ok_or_else(|| Error::from("Failed to read password: invalid Unicode data found")) + .map(ToOwned::to_owned) + } else { + pinentry::choose(&pwd_entry) + }?; device .create_hidden_volume(slot, start, end, &pwd) @@ -338,7 +345,14 @@ pub fn storage_hidden_create( pub fn storage_hidden_open(ctx: &mut args::ExecCtx<'_>) -> Result<()> { let device = get_storage_device(ctx)?; let pwd_entry = pinentry::PwdEntry::from(&device)?; - let pwd = pinentry::inquire(&pwd_entry, pinentry::Mode::Query, None)?; + let pwd = if let Some(pwd) = &ctx.password { + pwd + .to_str() + .ok_or_else(|| Error::from("Failed to read password: invalid Unicode data found")) + .map(ToOwned::to_owned) + } else { + pinentry::inquire(&pwd_entry, pinentry::Mode::Query, None) + }?; // We may forcefully close an encrypted volume, if active, so be sure // to flush caches to disk. diff --git a/nitrocli/src/main.rs b/nitrocli/src/main.rs index ff6db0f..58d0628 100644 --- a/nitrocli/src/main.rs +++ b/nitrocli/src/main.rs @@ -102,6 +102,7 @@ const NITROCLI_ADMIN_PIN: &str = "NITROCLI_ADMIN_PIN"; const NITROCLI_USER_PIN: &str = "NITROCLI_USER_PIN"; const NITROCLI_NEW_ADMIN_PIN: &str = "NITROCLI_NEW_ADMIN_PIN"; const NITROCLI_NEW_USER_PIN: &str = "NITROCLI_NEW_USER_PIN"; +const NITROCLI_PASSWORD: &str = "NITROCLI_PASSWORD"; /// The context used when running the program. pub(crate) struct RunCtx<'io> { @@ -121,6 +122,8 @@ pub(crate) struct RunCtx<'io> { /// /// This variable is only used by commands that change the user PIN. pub new_user_pin: Option, + /// A password used by some commands, if provided through an environment variable. + pub password: Option, } fn run<'ctx, 'io: 'ctx>(ctx: &'ctx mut RunCtx<'io>, args: Vec) -> i32 { @@ -154,6 +157,7 @@ fn main() { user_pin: env::var_os(NITROCLI_USER_PIN), new_admin_pin: env::var_os(NITROCLI_NEW_ADMIN_PIN), new_user_pin: env::var_os(NITROCLI_NEW_USER_PIN), + password: env::var_os(NITROCLI_PASSWORD), }; let rc = run(ctx, args); diff --git a/nitrocli/src/tests/mod.rs b/nitrocli/src/tests/mod.rs index a3855f8..0337029 100644 --- a/nitrocli/src/tests/mod.rs +++ b/nitrocli/src/tests/mod.rs @@ -77,6 +77,7 @@ struct Nitrocli { user_pin: Option, new_admin_pin: Option, new_user_pin: Option, + password: Option, } impl Nitrocli { @@ -87,6 +88,7 @@ impl Nitrocli { user_pin: Some(NITROKEY_DEFAULT_USER_PIN.into()), new_admin_pin: None, new_user_pin: None, + password: None, } } @@ -100,6 +102,7 @@ impl Nitrocli { user_pin: Some(NITROKEY_DEFAULT_USER_PIN.into()), new_admin_pin: None, new_user_pin: None, + password: Some("1234567".into()), }; drop(device); @@ -143,6 +146,7 @@ impl Nitrocli { user_pin: self.user_pin.clone(), new_admin_pin: self.new_admin_pin.clone(), new_user_pin: self.new_user_pin.clone(), + password: self.password.clone(), }; (f(ctx, args), stdout, stderr) diff --git a/nitrocli/src/tests/storage.rs b/nitrocli/src/tests/storage.rs index d017f34..be933ca 100644 --- a/nitrocli/src/tests/storage.rs +++ b/nitrocli/src/tests/storage.rs @@ -91,3 +91,27 @@ fn encrypted_open_close(device: nitrokey::Storage) -> crate::Result<()> { Ok(()) } + +#[test_device] +fn hidden_create_open_close(device: nitrokey::Storage) -> crate::Result<()> { + let mut ncli = Nitrocli::with_dev(device); + let out = ncli.handle(&["storage", "hidden", "create", "0", "50", "100"])?; + assert!(out.is_empty()); + + let out = ncli.handle(&["storage", "hidden", "open"])?; + assert!(out.is_empty()); + + let device = nitrokey::Storage::connect()?; + assert!(!device.get_status()?.encrypted_volume.active); + assert!(device.get_status()?.hidden_volume.active); + drop(device); + + let out = ncli.handle(&["storage", "hidden", "close"])?; + assert!(out.is_empty()); + + let device = nitrokey::Storage::connect()?; + assert!(!device.get_status()?.encrypted_volume.active); + assert!(!device.get_status()?.hidden_volume.active); + + Ok(()) +} -- cgit v1.2.1