aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Krahl <robin.krahl@ireas.org>2020-01-25 21:07:07 +0100
committerDaniel Mueller <deso@posteo.net>2021-01-10 17:37:55 -0800
commit0f163477f63d533f90b61c1f39423712567bf7ea (patch)
treef8bac7008f382e9b0dd425ed75422e9a9af7938f
parent0cc4371d138d5e98cd22813f10689cb089eef378 (diff)
downloadnitrocli-0f163477f63d533f90b61c1f39423712567bf7ea.tar.gz
nitrocli-0f163477f63d533f90b61c1f39423712567bf7ea.tar.bz2
Refactor connection handling
This patch introduces two new functions, find_device and connect, to connect to a Nitrokey device. find_device queries the attached Nitrokey devices, applies the filters (currently only the --model option) and returns the first match. connect calls find_device and connects to the returned device. This refactoring allows us to add more device filters, for example a --serial-number option, without code duplication.
-rw-r--r--src/commands.rs61
-rw-r--r--src/main.rs1
-rw-r--r--src/tests/status.rs7
3 files changed, 52 insertions, 17 deletions
diff --git a/src/commands.rs b/src/commands.rs
index 67d230e..ac3d020 100644
--- a/src/commands.rs
+++ b/src/commands.rs
@@ -6,6 +6,7 @@
use std::convert::TryFrom as _;
use std::fmt;
use std::mem;
+use std::ops::Deref as _;
use std::thread;
use std::time;
use std::u8;
@@ -20,6 +21,7 @@ use nitrokey::GenerateOtp;
use nitrokey::GetPasswordSafe;
use crate::args;
+use crate::config;
use crate::pinentry;
use crate::Context;
@@ -39,6 +41,45 @@ fn set_log_level(ctx: &mut Context<'_>) {
nitrokey::set_log_level(log_lvl);
}
+/// Create a filter string from the program configuration.
+fn format_filter(config: &config::Config) -> String {
+ if let Some(model) = config.model {
+ format!(" (filter: model={})", model.as_ref())
+ } else {
+ String::new()
+ }
+}
+
+/// Find a Nitrokey device that matches the given requirements
+fn find_device(config: &config::Config) -> anyhow::Result<nitrokey::DeviceInfo> {
+ let devices = nitrokey::list_devices().context("Failed to enumerate Nitrokey devices")?;
+ let nkmodel = config.model.map(nitrokey::Model::from);
+ let mut iter = devices
+ .into_iter()
+ .filter(|device| nkmodel.is_none() || device.model == nkmodel);
+
+ let device = iter
+ .next()
+ .with_context(|| format!("Nitrokey device not found{}", format_filter(config)))?;
+ Ok(device)
+}
+
+/// Connect to a Nitrokey device that matches the given requirements
+fn connect<'mgr>(
+ manager: &'mgr mut nitrokey::Manager,
+ config: &config::Config,
+) -> anyhow::Result<nitrokey::DeviceWrapper<'mgr>> {
+ let device_info = find_device(config)?;
+ manager
+ .connect_path(device_info.path.deref())
+ .with_context(|| {
+ format!(
+ "Failed to connect to Nitrokey device at path {}",
+ device_info.path
+ )
+ })
+}
+
/// Connect to any Nitrokey device and do something with it.
fn with_device<F>(ctx: &mut Context<'_>, op: F) -> anyhow::Result<()>
where
@@ -49,13 +90,7 @@ where
set_log_level(ctx);
- let device = match ctx.config.model {
- Some(model) => manager.connect_model(model.into()).with_context(|| {
- anyhow::anyhow!("Nitrokey {} device not found", model.as_user_facing_str())
- })?,
- None => manager.connect().context("Nitrokey device not found")?,
- };
-
+ let device = connect(&mut manager, &ctx.config)?;
op(ctx, device)
}
@@ -73,12 +108,16 @@ where
if model != args::DeviceModel::Storage {
anyhow::bail!("This command is only available on the Nitrokey Storage");
}
+ } else {
+ ctx.config.model = Some(args::DeviceModel::Storage);
}
- let device = manager
- .connect_storage()
- .context("Nitrokey Storage device not found")?;
- op(ctx, device)
+ let device = connect(&mut manager, &ctx.config)?;
+ if let nitrokey::DeviceWrapper::Storage(storage) = device {
+ op(ctx, storage)
+ } else {
+ panic!("connect returned a wrong model: {}", device.get_model())
+ }
}
/// Connect to any Nitrokey device, retrieve a password safe handle, and
diff --git a/src/main.rs b/src/main.rs
index baad15c..16715f9 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,6 +3,7 @@
// Copyright (C) 2017-2020 The Nitrocli Developers
// SPDX-License-Identifier: GPL-3.0-or-later
+#![allow(clippy::trivially_copy_pass_by_ref)]
#![warn(
bad_style,
dead_code,
diff --git a/src/tests/status.rs b/src/tests/status.rs
index d158103..fe69d78 100644
--- a/src/tests/status.rs
+++ b/src/tests/status.rs
@@ -11,12 +11,7 @@ fn not_found_raw() {
assert_ne!(rc, 0);
assert_eq!(out, b"");
- let expected = r#"Nitrokey device not found
-
-Caused by:
- Communication error: Could not connect to a Nitrokey device
-"#;
- assert_eq!(err, expected.as_bytes());
+ assert_eq!(err, b"Nitrokey device not found\n");
}
#[test_device]