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()),          }      } | 
