aboutsummaryrefslogtreecommitdiff
path: root/src/device.rs
diff options
context:
space:
mode:
authorRobin Krahl <robin.krahl@ireas.org>2019-01-27 18:42:14 +0000
committerRobin Krahl <robin.krahl@ireas.org>2019-07-08 21:40:17 +0000
commitfe2f39826ade5a156945dabb8c8ab725378a15c1 (patch)
treecd2c9d662dd93813524c5227c2c44e52cadde20e /src/device.rs
parent379bc798477a1de7ffda923c5d10ca63aebae25f (diff)
downloadnitrokey-rs-fe2f39826ade5a156945dabb8c8ab725378a15c1.tar.gz
nitrokey-rs-fe2f39826ade5a156945dabb8c8ab725378a15c1.tar.bz2
Store mutable reference to Manager in Device
In the last patches, we ensured that devices can only be obtained using the Manager struct. But we did not ensure that there is only one device at a time. This patch adds a mutable reference to the Manager instance to the Device implementations. The borrow checker makes sure that there is only one mutable reference at a time. In this patch, we have to remove the old connect, Pro::connect and Storage::connect functions as they do no longer compile. (They discard the MutexGuard which invalidates the reference to the Manager.) Therefore the tests do no longer compile.
Diffstat (limited to 'src/device.rs')
-rw-r--r--src/device.rs160
1 files changed, 40 insertions, 120 deletions
diff --git a/src/device.rs b/src/device.rs
index 758691d..50ff071 100644
--- a/src/device.rs
+++ b/src/device.rs
@@ -2,14 +2,13 @@
// SPDX-License-Identifier: MIT
use std::fmt;
-use std::marker;
use libc;
use nitrokey_sys;
use crate::auth::Authenticate;
use crate::config::{Config, RawConfig};
-use crate::error::Error;
+use crate::error::{CommunicationError, Error};
use crate::otp::GenerateOtp;
use crate::pws::GetPasswordSafe;
use crate::util::{
@@ -109,11 +108,11 @@ impl fmt::Display for VolumeMode {
///
/// [`connect`]: fn.connect.html
#[derive(Debug)]
-pub enum DeviceWrapper {
+pub enum DeviceWrapper<'a> {
/// A Nitrokey Storage device.
- Storage(Storage),
+ Storage(Storage<'a>),
/// A Nitrokey Pro device.
- Pro(Pro),
+ Pro(Pro<'a>),
}
/// A Nitrokey Pro device without user or admin authentication.
@@ -156,10 +155,8 @@ pub enum DeviceWrapper {
/// [`connect`]: fn.connect.html
/// [`Pro::connect`]: #method.connect
#[derive(Debug)]
-pub struct Pro {
- // make sure that users cannot directly instantiate this type
- #[doc(hidden)]
- marker: marker::PhantomData<()>,
+pub struct Pro<'a> {
+ manager: &'a mut crate::Manager,
}
/// A Nitrokey Storage device without user or admin authentication.
@@ -202,10 +199,8 @@ pub struct Pro {
/// [`connect`]: fn.connect.html
/// [`Storage::connect`]: #method.connect
#[derive(Debug)]
-pub struct Storage {
- // make sure that users cannot directly instantiate this type
- #[doc(hidden)]
- marker: marker::PhantomData<()>,
+pub struct Storage<'a> {
+ manager: &'a mut crate::Manager,
}
/// The status of a volume on a Nitrokey Storage device.
@@ -626,32 +621,6 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug {
}
}
-/// Connects to a Nitrokey device. This method can be used to connect to any connected device,
-/// both a Nitrokey Pro and a Nitrokey Storage.
-///
-/// # Errors
-///
-/// - [`NotConnected`][] if no Nitrokey device is connected
-///
-/// # Example
-///
-/// ```
-/// use nitrokey::DeviceWrapper;
-///
-/// fn do_something(device: DeviceWrapper) {}
-///
-/// match nitrokey::connect() {
-/// Ok(device) => do_something(device),
-/// Err(err) => eprintln!("Could not connect to a Nitrokey: {}", err),
-/// }
-/// ```
-///
-/// [`NotConnected`]: enum.CommunicationError.html#variant.NotConnected
-#[deprecated(since = "0.4.0", note = "use `nitrokey::Manager::connect` instead")]
-pub fn connect() -> Result<DeviceWrapper, Error> {
- crate::take()?.connect().map_err(Into::into)
-}
-
fn get_connected_model() -> Option<Model> {
match unsafe { nitrokey_sys::NK_get_device_model() } {
nitrokey_sys::NK_device_model_NK_PRO => Some(Model::Pro),
@@ -660,15 +629,23 @@ fn get_connected_model() -> Option<Model> {
}
}
-pub(crate) fn create_device_wrapper(model: Model) -> DeviceWrapper {
+pub(crate) fn create_device_wrapper(
+ manager: &mut crate::Manager,
+ model: Model,
+) -> DeviceWrapper<'_> {
match model {
- Model::Pro => Pro::new().into(),
- Model::Storage => Storage::new().into(),
+ Model::Pro => Pro::new(manager).into(),
+ Model::Storage => Storage::new(manager).into(),
}
}
-pub(crate) fn get_connected_device() -> Option<DeviceWrapper> {
- get_connected_model().map(create_device_wrapper)
+pub(crate) fn get_connected_device(
+ manager: &mut crate::Manager,
+) -> Result<DeviceWrapper<'_>, Error> {
+ match get_connected_model() {
+ Some(model) => Ok(create_device_wrapper(manager, model)),
+ None => Err(CommunicationError::NotConnected.into()),
+ }
}
pub(crate) fn connect_enum(model: Model) -> bool {
@@ -679,7 +656,7 @@ pub(crate) fn connect_enum(model: Model) -> bool {
unsafe { nitrokey_sys::NK_login_enum(model) == 1 }
}
-impl DeviceWrapper {
+impl<'a> DeviceWrapper<'a> {
fn device(&self) -> &dyn Device {
match *self {
DeviceWrapper::Storage(ref storage) => storage,
@@ -695,19 +672,19 @@ impl DeviceWrapper {
}
}
-impl From<Pro> for DeviceWrapper {
- fn from(device: Pro) -> Self {
+impl<'a> From<Pro<'a>> for DeviceWrapper<'a> {
+ fn from(device: Pro<'a>) -> Self {
DeviceWrapper::Pro(device)
}
}
-impl From<Storage> for DeviceWrapper {
- fn from(device: Storage) -> Self {
+impl<'a> From<Storage<'a>> for DeviceWrapper<'a> {
+ fn from(device: Storage<'a>) -> Self {
DeviceWrapper::Storage(device)
}
}
-impl GenerateOtp for DeviceWrapper {
+impl<'a> GenerateOtp for DeviceWrapper<'a> {
fn get_hotp_slot_name(&self, slot: u8) -> Result<String, Error> {
self.device().get_hotp_slot_name(slot)
}
@@ -725,7 +702,7 @@ impl GenerateOtp for DeviceWrapper {
}
}
-impl Device for DeviceWrapper {
+impl<'a> Device for DeviceWrapper<'a> {
fn get_model(&self) -> Model {
match *self {
DeviceWrapper::Pro(_) => Model::Pro,
@@ -734,40 +711,13 @@ impl Device for DeviceWrapper {
}
}
-impl Pro {
- /// Connects to a Nitrokey Pro.
- ///
- /// # Errors
- ///
- /// - [`NotConnected`][] if no Nitrokey device of the given model is connected
- ///
- /// # Example
- ///
- /// ```
- /// use nitrokey::Pro;
- ///
- /// fn use_pro(device: Pro) {}
- ///
- /// match nitrokey::Pro::connect() {
- /// Ok(device) => use_pro(device),
- /// Err(err) => eprintln!("Could not connect to the Nitrokey Pro: {}", err),
- /// }
- /// ```
- ///
- /// [`NotConnected`]: enum.CommunicationError.html#variant.NotConnected
- #[deprecated(since = "0.4.0", note = "use `nitrokey::Manager::connect_pro` instead")]
- pub fn connect() -> Result<Pro, Error> {
- crate::take()?.connect_pro().map_err(Into::into)
- }
-
- pub(crate) fn new() -> Pro {
- Pro {
- marker: marker::PhantomData,
- }
+impl<'a> Pro<'a> {
+ pub(crate) fn new(manager: &'a mut crate::Manager) -> Pro<'a> {
+ Pro { manager }
}
}
-impl Drop for Pro {
+impl<'a> Drop for Pro<'a> {
fn drop(&mut self) {
unsafe {
nitrokey_sys::NK_logout();
@@ -775,47 +725,17 @@ impl Drop for Pro {
}
}
-impl Device for Pro {
+impl<'a> Device for Pro<'a> {
fn get_model(&self) -> Model {
Model::Pro
}
}
-impl GenerateOtp for Pro {}
+impl<'a> GenerateOtp for Pro<'a> {}
-impl Storage {
- /// Connects to a Nitrokey Storage.
- ///
- /// # Errors
- ///
- /// - [`NotConnected`][] if no Nitrokey device of the given model is connected
- ///
- /// # Example
- ///
- /// ```
- /// use nitrokey::Storage;
- ///
- /// fn use_storage(device: Storage) {}
- ///
- /// match nitrokey::Storage::connect() {
- /// Ok(device) => use_storage(device),
- /// Err(err) => eprintln!("Could not connect to the Nitrokey Storage: {}", err),
- /// }
- /// ```
- ///
- /// [`NotConnected`]: enum.CommunicationError.html#variant.NotConnected
- #[deprecated(
- since = "0.4.0",
- note = "use `nitrokey::Manager::connect_storage` instead"
- )]
- pub fn connect() -> Result<Storage, Error> {
- crate::take()?.connect_storage().map_err(Into::into)
- }
-
- pub(crate) fn new() -> Storage {
- Storage {
- marker: marker::PhantomData,
- }
+impl<'a> Storage<'a> {
+ pub(crate) fn new(manager: &'a mut crate::Manager) -> Storage<'a> {
+ Storage { manager }
}
/// Changes the update PIN.
@@ -1320,7 +1240,7 @@ impl Storage {
}
}
-impl Drop for Storage {
+impl<'a> Drop for Storage<'a> {
fn drop(&mut self) {
unsafe {
nitrokey_sys::NK_logout();
@@ -1328,13 +1248,13 @@ impl Drop for Storage {
}
}
-impl Device for Storage {
+impl<'a> Device for Storage<'a> {
fn get_model(&self) -> Model {
Model::Storage
}
}
-impl GenerateOtp for Storage {}
+impl<'a> GenerateOtp for Storage<'a> {}
impl From<nitrokey_sys::NK_storage_ProductionTest> for StorageProductionInfo {
fn from(data: nitrokey_sys::NK_storage_ProductionTest) -> Self {