From 44b1e6e2f2be7cbed140db81198230bbbe542a37 Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Fri, 26 Mar 2021 17:05:39 +0100 Subject: [PATCH] Use new PWS access API In previous versions of nitrokey-rs, the getters for the name, login and password fields of a PWS slot would return an error for empty strings as libnitrokey uses empty strings to indicate unprogrammed slots. But as the user might have deliberately specified an empty value, nitrokey-rs v0.9.0 introduces a new PWS API that makes it possible to distinguish unprogrammed slots and empty values. This patch updates the nitrokey-rs dependency and refactors the pws status and pws get commands to use the new PWS API. --- CHANGELOG.md | 6 ++++++ Cargo.lock | 4 ++-- Cargo.toml | 2 +- src/commands.rs | 49 ++++++++++++++++-------------------------------- src/tests/pws.rs | 24 +++++++++++++++++++++++- 5 files changed, 48 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 147e6911..1b60f746 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +Unreleased +---------- +- Enabled usage of empty PWS slot fields +- Bumped `nitrokey` dependency to `0.9.0` + + 0.4.0 ----- - Added support for the Librem Key diff --git a/Cargo.lock b/Cargo.lock index db8f54cb..a644916e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -235,9 +235,9 @@ dependencies = [ [[package]] name = "nitrokey" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48059f1f469143fd371228e33893e6c76419daa9dcb8c0fac2bc1ef2fdfbb7b1" +checksum = "ddeb2d19d5499ab4740c0131562e8c4b2c13f8954677be4318c1efc944911531" dependencies = [ "lazy_static", "libc", diff --git a/Cargo.toml b/Cargo.toml index c7e968d8..6bb42e53 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,7 @@ version = "0.2" version = "0.1" [dependencies.nitrokey] -version = "0.8" +version = "0.9.0" [dependencies.progressing] version = "3.0.2" diff --git a/src/commands.rs b/src/commands.rs index 7612b76e..f1add9b3 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -4,7 +4,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later use std::borrow; -use std::convert::TryFrom as _; use std::env; use std::ffi; use std::fmt; @@ -996,20 +995,6 @@ fn print_pws_data( Ok(()) } -fn check_slot(pws: &nitrokey::PasswordSafe<'_, '_>, slot: u8) -> anyhow::Result<()> { - if slot >= nitrokey::SLOT_COUNT { - anyhow::bail!("Slot {} is not valid", slot); - } - let status = pws - .get_slot_status() - .context("Failed to read PWS slot status")?; - if status[slot as usize] { - Ok(()) - } else { - anyhow::bail!("Slot {} is not programmed", slot) - } -} - /// Read a PWS slot. pub fn pws_get( ctx: &mut Context<'_>, @@ -1020,17 +1005,17 @@ pub fn pws_get( quiet: bool, ) -> anyhow::Result<()> { with_password_safe(ctx, |ctx, pws| { - check_slot(&pws, slot).context("Failed to access PWS slot")?; + let slot = pws.get_slot(slot).context("Failed to access PWS slot")?; let show_all = !show_name && !show_login && !show_password; if show_all || show_name { - print_pws_data(ctx, "name: ", pws.get_slot_name(slot), quiet)?; + print_pws_data(ctx, "name: ", slot.get_name(), quiet)?; } if show_all || show_login { - print_pws_data(ctx, "login: ", pws.get_slot_login(slot), quiet)?; + print_pws_data(ctx, "login: ", slot.get_login(), quiet)?; } if show_all || show_password { - print_pws_data(ctx, "password:", pws.get_slot_password(slot), quiet)?; + print_pws_data(ctx, "password:", slot.get_password(), quiet)?; } Ok(()) }) @@ -1060,31 +1045,29 @@ pub fn pws_clear(ctx: &mut Context<'_>, slot: u8) -> anyhow::Result<()> { fn print_pws_slot( ctx: &mut Context<'_>, - pws: &nitrokey::PasswordSafe<'_, '_>, - slot: usize, - programmed: bool, + index: usize, + slot: Option>, ) -> anyhow::Result<()> { - let slot = u8::try_from(slot).map_err(|_| anyhow::anyhow!("Invalid PWS slot number"))?; - let name = if programmed { - pws - .get_slot_name(slot) - .context("Failed to read PWS slot name")? + let name = if let Some(slot) = slot { + slot.get_name().context("Failed to read PWS slot name")? } else { "[not programmed]".to_string() }; - println!(ctx, "{}\t{}", slot, name)?; + println!(ctx, "{}\t{}", index, name)?; Ok(()) } /// Print the status of all PWS slots. pub fn pws_status(ctx: &mut Context<'_>, all: bool) -> anyhow::Result<()> { with_password_safe(ctx, |ctx, pws| { - let slots = pws - .get_slot_status() - .context("Failed to read PWS slot status")?; + let slots = pws.get_slots().context("Failed to read PWS slot status")?; println!(ctx, "slot\tname")?; - for (i, &value) in slots.iter().enumerate().filter(|(_, &value)| all || value) { - print_pws_slot(ctx, &pws, i, value)?; + for (i, &slot) in slots + .iter() + .enumerate() + .filter(|(_, &slot)| all || slot.is_some()) + { + print_pws_slot(ctx, i, slot)?; } Ok(()) }) diff --git a/src/tests/pws.rs b/src/tests/pws.rs index cdead848..15488337 100644 --- a/src/tests/pws.rs +++ b/src/tests/pws.rs @@ -1,6 +1,6 @@ // pws.rs -// Copyright (C) 2019-2020 The Nitrocli Developers +// Copyright (C) 2019-2021 The Nitrocli Developers // SPDX-License-Identifier: GPL-3.0-or-later use super::*; @@ -66,6 +66,28 @@ fn set_get(model: nitrokey::Model) -> anyhow::Result<()> { Ok(()) } +#[test_device] +fn set_empty(model: nitrokey::Model) -> anyhow::Result<()> { + let mut ncli = Nitrocli::new().model(model); + let _ = ncli.handle(&["pws", "set", "1", "", "", ""])?; + + let out = ncli.handle(&["pws", "get", "1", "--quiet", "--name"])?; + assert_eq!(out, "\n"); + + let out = ncli.handle(&["pws", "get", "1", "--quiet", "--login"])?; + assert_eq!(out, "\n"); + + let out = ncli.handle(&["pws", "get", "1", "--quiet", "--password"])?; + assert_eq!(out, "\n"); + + let out = ncli.handle(&["pws", "get", "1", "--quiet"])?; + assert_eq!(out, "\n\n\n"); + + let out = ncli.handle(&["pws", "get", "1"])?; + assert_eq!(out, "name: \nlogin: \npassword: \n",); + Ok(()) +} + #[test_device] fn set_reset_get(model: nitrokey::Model) -> anyhow::Result<()> { const NAME: &str = "some/svc";