aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Krahl <robin.krahl@ireas.org>2019-01-23 02:29:00 +0000
committerRobin Krahl <robin.krahl@ireas.org>2019-01-23 03:31:45 +0100
commit57e3c6bf010d51842cbc86a9801fd9baee1b22eb (patch)
tree006ee62941ddca15a3622992ee4c2714087a4140
parent07bb11fec9de6579ffaa8d128796f242f818292f (diff)
downloadnitrokey-rs-57e3c6bf010d51842cbc86a9801fd9baee1b22eb.tar.gz
nitrokey-rs-57e3c6bf010d51842cbc86a9801fd9baee1b22eb.tar.bz2
Prevent direct instantiation of Pro and Storage
The Pro and Storage structs may only be created using the connect functions. This patch adds a private PhantomData field to the structs to ensure that the compiler does not allow direct instantiation.
-rw-r--r--CHANGELOG.md2
-rw-r--r--TODO.md1
-rw-r--r--src/device.rs29
3 files changed, 25 insertions, 7 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a4df5c6..1e962e0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,8 @@
- Return `CommunicationError::NotConnected` instead of
`CommandError::Undefined` from the connect functions.
- Remove the `CommandError::Undefined` variant.
+- Add a private `PhantomData` field to `Pro` and `Storage` to make direct
+ instantiation impossible.
# v0.3.4 (2019-01-20)
- Fix authentication methods that assumed that `char` is signed.
diff --git a/TODO.md b/TODO.md
index 487f56d..8f4e348 100644
--- a/TODO.md
+++ b/TODO.md
@@ -8,7 +8,6 @@
- Fix timing issues with the `totp_no_pin` and `totp_pin` test cases.
- Clear passwords from memory.
- Find a nicer syntax for the `write_config` test.
-- Prevent construction of internal types.
- Check integer conversions.
- Consider implementing `Into<CommandError>` for `(Device, CommandError)`
- Lock password safe in `PasswordSafe::drop()` (see [nitrokey-storage-firmware
diff --git a/src/device.rs b/src/device.rs
index 16064c3..40d6ba4 100644
--- a/src/device.rs
+++ b/src/device.rs
@@ -1,4 +1,5 @@
use std::fmt;
+use std::marker;
use libc;
use nitrokey_sys;
@@ -154,7 +155,11 @@ pub enum DeviceWrapper {
/// [`connect`]: fn.connect.html
/// [`Pro::connect`]: #method.connect
#[derive(Debug)]
-pub struct Pro {}
+pub struct Pro {
+ // make sure that users cannot directly instantiate this type
+ #[doc(hidden)]
+ marker: marker::PhantomData<()>,
+}
/// A Nitrokey Storage device without user or admin authentication.
///
@@ -196,7 +201,11 @@ pub struct Pro {}
/// [`connect`]: fn.connect.html
/// [`Storage::connect`]: #method.connect
#[derive(Debug)]
-pub struct Storage {}
+pub struct Storage {
+ // make sure that users cannot directly instantiate this type
+ #[doc(hidden)]
+ marker: marker::PhantomData<()>,
+}
/// The status of a volume on a Nitrokey Storage device.
#[derive(Debug)]
@@ -713,8 +722,12 @@ fn get_connected_model() -> Option<Model> {
fn create_device_wrapper(model: Model) -> DeviceWrapper {
match model {
- Model::Pro => DeviceWrapper::Pro(Pro {}),
- Model::Storage => DeviceWrapper::Storage(Storage {}),
+ Model::Pro => DeviceWrapper::Pro(Pro {
+ marker: marker::PhantomData,
+ }),
+ Model::Storage => DeviceWrapper::Storage(Storage {
+ marker: marker::PhantomData,
+ }),
}
}
@@ -790,7 +803,9 @@ impl Pro {
pub fn connect() -> Result<Pro, Error> {
// TODO: maybe Option instead of Result?
match connect_enum(Model::Pro) {
- true => Ok(Pro {}),
+ true => Ok(Pro {
+ marker: marker::PhantomData,
+ }),
false => Err(CommunicationError::NotConnected.into()),
}
}
@@ -836,7 +851,9 @@ impl Storage {
pub fn connect() -> Result<Storage, Error> {
// TODO: maybe Option instead of Result?
match connect_enum(Model::Storage) {
- true => Ok(Storage {}),
+ true => Ok(Storage {
+ marker: marker::PhantomData,
+ }),
false => Err(CommunicationError::NotConnected.into()),
}
}