diff options
author | Robin Krahl <robin.krahl@ireas.org> | 2019-01-23 02:29:00 +0000 |
---|---|---|
committer | Robin Krahl <robin.krahl@ireas.org> | 2019-01-23 03:31:45 +0100 |
commit | 57e3c6bf010d51842cbc86a9801fd9baee1b22eb (patch) | |
tree | 006ee62941ddca15a3622992ee4c2714087a4140 | |
parent | 07bb11fec9de6579ffaa8d128796f242f818292f (diff) | |
download | nitrokey-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.md | 2 | ||||
-rw-r--r-- | TODO.md | 1 | ||||
-rw-r--r-- | src/device.rs | 29 |
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. @@ -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()), } } |