diff options
| author | Robin Krahl <robin.krahl@ireas.org> | 2019-02-05 12:47:24 +0000 | 
|---|---|---|
| committer | Robin Krahl <robin.krahl@ireas.org> | 2019-02-05 14:48:24 +0000 | 
| commit | 83641ca0518e4c766c63e40d0787e4f0b436652a (patch) | |
| tree | 2993e03fa920a9045c7b2a32c742098601fcd5ba /src | |
| parent | 606177a61de39ba5e96390d63cff536f895d8c39 (diff) | |
| download | nitrokey-rs-83641ca0518e4c766c63e40d0787e4f0b436652a.tar.gz nitrokey-rs-83641ca0518e4c766c63e40d0787e4f0b436652a.tar.bz2 | |
Revert "Refactor User and Admin to use a mutable reference"
This reverts commit 0972bbe82623c3d9649b6023d8f50d304aa0cde6.
Diffstat (limited to 'src')
| -rw-r--r-- | src/auth.rs | 183 | ||||
| -rw-r--r-- | src/device.rs | 42 | ||||
| -rw-r--r-- | src/lib.rs | 4 | ||||
| -rw-r--r-- | src/otp.rs | 16 | 
4 files changed, 170 insertions, 75 deletions
| diff --git a/src/auth.rs b/src/auth.rs index 573fed3..f9f50fa 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -42,10 +42,16 @@ pub trait Authenticate {      /// fn perform_other_task(device: &DeviceWrapper) {}      ///      /// # fn try_main() -> Result<(), Error> { -    /// let mut device = nitrokey::connect()?; -    /// match device.authenticate_user("123456") { -    ///     Ok(user) => perform_user_task(&user), -    ///     Err(err) => eprintln!("Could not authenticate as user: {}", err), +    /// let device = nitrokey::connect()?; +    /// let device = match device.authenticate_user("123456") { +    ///     Ok(user) => { +    ///         perform_user_task(&user); +    ///         user.device() +    ///     }, +    ///     Err((device, err)) => { +    ///         eprintln!("Could not authenticate as user: {}", err); +    ///         device +    ///     },      /// };      /// perform_other_task(&device);      /// #     Ok(()) @@ -55,9 +61,9 @@ pub trait Authenticate {      /// [`InvalidString`]: enum.LibraryError.html#variant.InvalidString      /// [`RngError`]: enum.CommandError.html#variant.RngError      /// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword -    fn authenticate_user(&mut self, password: &str) -> Result<User<'_, Self>, Error> +    fn authenticate_user(self, password: &str) -> Result<User<Self>, (Self, Error)>      where -        Self: Device + std::marker::Sized; +        Self: Device + Sized;      /// Performs admin authentication.  This method consumes the device.  If successful, an      /// authenticated device is returned.  Otherwise, the current unauthenticated device and the @@ -82,10 +88,16 @@ pub trait Authenticate {      /// fn perform_other_task(device: &DeviceWrapper) {}      ///      /// # fn try_main() -> Result<(), Error> { -    /// let mut device = nitrokey::connect()?; -    /// match device.authenticate_admin("123456") { -    ///     Ok(admin) => perform_admin_task(&admin), -    ///     Err(err) => eprintln!("Could not authenticate as admin: {}", err), +    /// let device = nitrokey::connect()?; +    /// let device = match device.authenticate_admin("123456") { +    ///     Ok(admin) => { +    ///         perform_admin_task(&admin); +    ///         admin.device() +    ///     }, +    ///     Err((device, err)) => { +    ///         eprintln!("Could not authenticate as admin: {}", err); +    ///         device +    ///     },      /// };      /// perform_other_task(&device);      /// #     Ok(()) @@ -95,13 +107,13 @@ pub trait Authenticate {      /// [`InvalidString`]: enum.LibraryError.html#variant.InvalidString      /// [`RngError`]: enum.CommandError.html#variant.RngError      /// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword -    fn authenticate_admin(&mut self, password: &str) -> Result<Admin<'_, Self>, Error> +    fn authenticate_admin(self, password: &str) -> Result<Admin<Self>, (Self, Error)>      where -        Self: Device + std::marker::Sized; +        Self: Device + Sized;  } -trait AuthenticatedDevice<'a, T> { -    fn new(device: &'a mut T, temp_password: Vec<u8>) -> Self; +trait AuthenticatedDevice<T> { +    fn new(device: T, temp_password: Vec<u8>) -> Self;      fn temp_password_ptr(&self) -> *const c_char;  } @@ -116,8 +128,8 @@ trait AuthenticatedDevice<'a, T> {  /// [`authenticate_admin`]: trait.Authenticate.html#method.authenticate_admin  /// [`device`]: #method.device  #[derive(Debug)] -pub struct User<'a, T: Device> { -    device: &'a mut T, +pub struct User<T: Device> { +    device: T,      temp_password: Vec<u8>,  } @@ -131,42 +143,89 @@ pub struct User<'a, T: Device> {  /// [`authenticate_admin`]: trait.Authenticate.html#method.authenticate_admin  /// [`device`]: #method.device  #[derive(Debug)] -pub struct Admin<'a, T: Device> { -    device: &'a mut T, +pub struct Admin<T: Device> { +    device: T,      temp_password: Vec<u8>,  } -fn authenticate<'a, D, A, T>(device: &'a mut D, password: &str, callback: T) -> Result<A, Error> +fn authenticate<D, A, T>(device: D, password: &str, callback: T) -> Result<A, (D, Error)>  where      D: Device, -    A: AuthenticatedDevice<'a, D>, +    A: AuthenticatedDevice<D>,      T: Fn(*const c_char, *const c_char) -> c_int,  { -    let temp_password = generate_password(TEMPORARY_PASSWORD_LENGTH)?; -    let password = get_cstring(password)?; +    let temp_password = match generate_password(TEMPORARY_PASSWORD_LENGTH) { +        Ok(temp_password) => temp_password, +        Err(err) => return Err((device, err)), +    }; +    let password = match get_cstring(password) { +        Ok(password) => password, +        Err(err) => return Err((device, err)), +    };      let password_ptr = password.as_ptr();      let temp_password_ptr = temp_password.as_ptr() as *const c_char;      match callback(password_ptr, temp_password_ptr) {          0 => Ok(A::new(device, temp_password)), -        rv => Err(Error::from(rv)), +        rv => Err((device, Error::from(rv))),      }  } -impl<'a, T: Device> ops::Deref for User<'a, T> { +fn authenticate_user_wrapper<T, C>( +    device: T, +    constructor: C, +    password: &str, +) -> Result<User<DeviceWrapper>, (DeviceWrapper, Error)> +where +    T: Device, +    C: Fn(T) -> DeviceWrapper, +{ +    let result = device.authenticate_user(password); +    match result { +        Ok(user) => Ok(User::new(constructor(user.device), user.temp_password)), +        Err((device, err)) => Err((constructor(device), err)), +    } +} + +fn authenticate_admin_wrapper<T, C>( +    device: T, +    constructor: C, +    password: &str, +) -> Result<Admin<DeviceWrapper>, (DeviceWrapper, Error)> +where +    T: Device, +    C: Fn(T) -> DeviceWrapper, +{ +    let result = device.authenticate_admin(password); +    match result { +        Ok(user) => Ok(Admin::new(constructor(user.device), user.temp_password)), +        Err((device, err)) => Err((constructor(device), err)), +    } +} + +impl<T: Device> User<T> { +    /// Forgets the user authentication and returns an unauthenticated device.  This method +    /// consumes the authenticated device.  It does not perform any actual commands on the +    /// Nitrokey. +    pub fn device(self) -> T { +        self.device +    } +} + +impl<T: Device> ops::Deref for User<T> {      type Target = T;      fn deref(&self) -> &Self::Target { -        self.device +        &self.device      }  } -impl<'a, T: Device> ops::DerefMut for User<'a, T> { +impl<T: Device> ops::DerefMut for User<T> {      fn deref_mut(&mut self) -> &mut T { -        self.device +        &mut self.device      }  } -impl<'a, T: Device> GenerateOtp for User<'a, T> { +impl<T: Device> GenerateOtp for User<T> {      fn get_hotp_code(&mut self, slot: u8) -> Result<String, Error> {          result_from_string(unsafe {              nitrokey_sys::NK_get_hotp_code_PIN(slot, self.temp_password_ptr()) @@ -180,8 +239,8 @@ impl<'a, T: Device> GenerateOtp for User<'a, T> {      }  } -impl<'a, T: Device> AuthenticatedDevice<'a, T> for User<'a, T> { -    fn new(device: &'a mut T, temp_password: Vec<u8>) -> Self { +impl<T: Device> AuthenticatedDevice<T> for User<T> { +    fn new(device: T, temp_password: Vec<u8>) -> Self {          User {              device,              temp_password, @@ -193,21 +252,28 @@ impl<'a, T: Device> AuthenticatedDevice<'a, T> for User<'a, T> {      }  } -impl<'a, T: Device> ops::Deref for Admin<'a, T> { +impl<T: Device> ops::Deref for Admin<T> {      type Target = T;      fn deref(&self) -> &Self::Target { -        self.device +        &self.device      }  } -impl<'a, T: Device> ops::DerefMut for Admin<'a, T> { +impl<T: Device> ops::DerefMut for Admin<T> {      fn deref_mut(&mut self) -> &mut T { -        self.device +        &mut self.device      }  } -impl<'a, T: Device> Admin<'a, T> { +impl<T: Device> Admin<T> { +    /// Forgets the user authentication and returns an unauthenticated device.  This method +    /// consumes the authenticated device.  It does not perform any actual commands on the +    /// Nitrokey. +    pub fn device(self) -> T { +        self.device +    } +      /// Writes the given configuration to the Nitrokey device.      ///      /// # Errors @@ -221,11 +287,14 @@ impl<'a, T: Device> Admin<'a, T> {      /// # use nitrokey::Error;      ///      /// # fn try_main() -> Result<(), Error> { -    /// let mut device = nitrokey::connect()?; +    /// let device = nitrokey::connect()?;      /// let config = Config::new(None, None, None, false);      /// match device.authenticate_admin("12345678") { -    ///     Ok(mut admin) => admin.write_config(config)?, -    ///     Err(err) => eprintln!("Could not authenticate as admin: {}", err), +    ///     Ok(mut admin) => { +    ///         admin.write_config(config); +    ///         () +    ///     }, +    ///     Err((_, err)) => eprintln!("Could not authenticate as admin: {}", err),      /// };      /// #     Ok(())      /// # } @@ -247,7 +316,7 @@ impl<'a, T: Device> Admin<'a, T> {      }  } -impl<'a, T: Device> ConfigureOtp for Admin<'a, T> { +impl<T: Device> ConfigureOtp for Admin<T> {      fn write_hotp_slot(&mut self, data: OtpSlotData, counter: u64) -> Result<(), Error> {          let raw_data = RawOtpSlotData::new(data)?;          get_command_result(unsafe { @@ -295,8 +364,8 @@ impl<'a, T: Device> ConfigureOtp for Admin<'a, T> {      }  } -impl<'a, T: Device> AuthenticatedDevice<'a, T> for Admin<'a, T> { -    fn new(device: &'a mut T, temp_password: Vec<u8>) -> Self { +impl<T: Device> AuthenticatedDevice<T> for Admin<T> { +    fn new(device: T, temp_password: Vec<u8>) -> Self {          Admin {              device,              temp_password, @@ -309,27 +378,35 @@ impl<'a, T: Device> AuthenticatedDevice<'a, T> for Admin<'a, T> {  }  impl Authenticate for DeviceWrapper { -    fn authenticate_user(&mut self, password: &str) -> Result<User<'_, Self>, Error> { -        authenticate(self, password, |password_ptr, temp_password_ptr| unsafe { -            nitrokey_sys::NK_user_authenticate(password_ptr, temp_password_ptr) -        }) +    fn authenticate_user(self, password: &str) -> Result<User<Self>, (Self, Error)> { +        match self { +            DeviceWrapper::Storage(storage) => { +                authenticate_user_wrapper(storage, DeviceWrapper::Storage, password) +            } +            DeviceWrapper::Pro(pro) => authenticate_user_wrapper(pro, DeviceWrapper::Pro, password), +        }      } -    fn authenticate_admin(&mut self, password: &str) -> Result<Admin<'_, Self>, Error> { -        authenticate(self, password, |password_ptr, temp_password_ptr| unsafe { -            nitrokey_sys::NK_user_authenticate(password_ptr, temp_password_ptr) -        }) +    fn authenticate_admin(self, password: &str) -> Result<Admin<Self>, (Self, Error)> { +        match self { +            DeviceWrapper::Storage(storage) => { +                authenticate_admin_wrapper(storage, DeviceWrapper::Storage, password) +            } +            DeviceWrapper::Pro(pro) => { +                authenticate_admin_wrapper(pro, DeviceWrapper::Pro, password) +            } +        }      }  }  impl Authenticate for Pro { -    fn authenticate_user(&mut self, password: &str) -> Result<User<'_, Self>, Error> { +    fn authenticate_user(self, password: &str) -> Result<User<Self>, (Self, Error)> {          authenticate(self, password, |password_ptr, temp_password_ptr| unsafe {              nitrokey_sys::NK_user_authenticate(password_ptr, temp_password_ptr)          })      } -    fn authenticate_admin(&mut self, password: &str) -> Result<Admin<'_, Self>, Error> { +    fn authenticate_admin(self, password: &str) -> Result<Admin<Self>, (Self, Error)> {          authenticate(self, password, |password_ptr, temp_password_ptr| unsafe {              nitrokey_sys::NK_first_authenticate(password_ptr, temp_password_ptr)          }) @@ -337,13 +414,13 @@ impl Authenticate for Pro {  }  impl Authenticate for Storage { -    fn authenticate_user(&mut self, password: &str) -> Result<User<'_, Self>, Error> { +    fn authenticate_user(self, password: &str) -> Result<User<Self>, (Self, Error)> {          authenticate(self, password, |password_ptr, temp_password_ptr| unsafe {              nitrokey_sys::NK_user_authenticate(password_ptr, temp_password_ptr)          })      } -    fn authenticate_admin(&mut self, password: &str) -> Result<Admin<'_, Self>, Error> { +    fn authenticate_admin(self, password: &str) -> Result<Admin<Self>, (Self, Error)> {          authenticate(self, password, |password_ptr, temp_password_ptr| unsafe {              nitrokey_sys::NK_first_authenticate(password_ptr, temp_password_ptr)          }) diff --git a/src/device.rs b/src/device.rs index a0df30e..f6492cd 100644 --- a/src/device.rs +++ b/src/device.rs @@ -71,10 +71,16 @@ impl fmt::Display for VolumeMode {  /// fn perform_other_task(device: &DeviceWrapper) {}  ///  /// # fn try_main() -> Result<(), Error> { -/// let mut device = nitrokey::connect()?; -/// match device.authenticate_user("123456") { -///     Ok(user) => perform_user_task(&user), -///     Err(err) => eprintln!("Could not authenticate as user: {}", err), +/// let device = nitrokey::connect()?; +/// let device = match device.authenticate_user("123456") { +///     Ok(user) => { +///         perform_user_task(&user); +///         user.device() +///     }, +///     Err((device, err)) => { +///         eprintln!("Could not authenticate as user: {}", err); +///         device +///     },  /// };  /// perform_other_task(&device);  /// #     Ok(()) @@ -129,10 +135,16 @@ pub enum DeviceWrapper {  /// fn perform_other_task(device: &Pro) {}  ///  /// # fn try_main() -> Result<(), Error> { -/// let mut device = nitrokey::Pro::connect()?; -/// match device.authenticate_user("123456") { -///     Ok(user) => perform_user_task(&user), -///     Err(err) => eprintln!("Could not authenticate as user: {}", err), +/// let device = nitrokey::Pro::connect()?; +/// let device = match device.authenticate_user("123456") { +///     Ok(user) => { +///         perform_user_task(&user); +///         user.device() +///     }, +///     Err((device, err)) => { +///         eprintln!("Could not authenticate as user: {}", err); +///         device +///     },  /// };  /// perform_other_task(&device);  /// #     Ok(()) @@ -169,10 +181,16 @@ pub struct Pro {  /// fn perform_other_task(device: &Storage) {}  ///  /// # fn try_main() -> Result<(), Error> { -/// let mut device = nitrokey::Storage::connect()?; -/// match device.authenticate_user("123456") { -///     Ok(user) => perform_user_task(&user), -///     Err(err) => eprintln!("Could not authenticate as user: {}", err), +/// let device = nitrokey::Storage::connect()?; +/// let device = match device.authenticate_user("123456") { +///     Ok(user) => { +///         perform_user_task(&user); +///         user.device() +///     }, +///     Err((device, err)) => { +///         eprintln!("Could not authenticate as user: {}", err); +///         device +///     },  /// };  /// perform_other_task(&device);  /// #     Ok(()) @@ -44,7 +44,7 @@  //! # use nitrokey::Error;  //!  //! # fn try_main() -> Result<(), Error> { -//! let mut device = nitrokey::connect()?; +//! let device = nitrokey::connect()?;  //! let slot_data = OtpSlotData::new(1, "test", "01234567890123456689", OtpMode::SixDigits);  //! match device.authenticate_admin("12345678") {  //!     Ok(mut admin) => { @@ -53,7 +53,7 @@  //!             Err(err) => eprintln!("Could not write slot: {}", err),  //!         }  //!     }, -//!     Err(err) => eprintln!("Could not authenticate as admin: {}", err), +//!     Err((_, err)) => eprintln!("Could not authenticate as admin: {}", err),  //! }  //! #     Ok(())  //! # } @@ -35,7 +35,7 @@ pub trait ConfigureOtp {      /// # use nitrokey::Error;      ///      /// # fn try_main() -> Result<(), Error> { -    /// let mut device = nitrokey::connect()?; +    /// let device = nitrokey::connect()?;      /// let slot_data = OtpSlotData::new(1, "test", "01234567890123456689", OtpMode::SixDigits);      /// match device.authenticate_admin("12345678") {      ///     Ok(mut admin) => { @@ -44,7 +44,7 @@ pub trait ConfigureOtp {      ///             Err(err) => eprintln!("Could not write slot: {}", err),      ///         }      ///     }, -    ///     Err(err) => eprintln!("Could not authenticate as admin: {}", err), +    ///     Err((_, err)) => eprintln!("Could not authenticate as admin: {}", err),      /// }      /// #     Ok(())      /// # } @@ -71,7 +71,7 @@ pub trait ConfigureOtp {      /// # use nitrokey::Error;      ///      /// # fn try_main() -> Result<(), Error> { -    /// let mut device = nitrokey::connect()?; +    /// let device = nitrokey::connect()?;      /// let slot_data = OtpSlotData::new(1, "test", "01234567890123456689", OtpMode::EightDigits);      /// match device.authenticate_admin("12345678") {      ///     Ok(mut admin) => { @@ -80,7 +80,7 @@ pub trait ConfigureOtp {      ///             Err(err) => eprintln!("Could not write slot: {}", err),      ///         }      ///     }, -    ///     Err(err) => eprintln!("Could not authenticate as admin: {}", err), +    ///     Err((_, err)) => eprintln!("Could not authenticate as admin: {}", err),      /// }      /// #     Ok(())      /// # } @@ -104,7 +104,7 @@ pub trait ConfigureOtp {      /// # use nitrokey::Error;      ///      /// # fn try_main() -> Result<(), Error> { -    /// let mut device = nitrokey::connect()?; +    /// let device = nitrokey::connect()?;      /// match device.authenticate_admin("12345678") {      ///     Ok(mut admin) => {      ///         match admin.erase_hotp_slot(1) { @@ -112,7 +112,7 @@ pub trait ConfigureOtp {      ///             Err(err) => eprintln!("Could not erase slot: {}", err),      ///         }      ///     }, -    ///     Err(err) => eprintln!("Could not authenticate as admin: {}", err), +    ///     Err((_, err)) => eprintln!("Could not authenticate as admin: {}", err),      /// }      /// #     Ok(())      /// # } @@ -134,7 +134,7 @@ pub trait ConfigureOtp {      /// # use nitrokey::Error;      ///      /// # fn try_main() -> Result<(), Error> { -    /// let mut device = nitrokey::connect()?; +    /// let device = nitrokey::connect()?;      /// match device.authenticate_admin("12345678") {      ///     Ok(mut admin) => {      ///         match admin.erase_totp_slot(1) { @@ -142,7 +142,7 @@ pub trait ConfigureOtp {      ///             Err(err) => eprintln!("Could not erase slot: {}", err),      ///         }      ///     }, -    ///     Err(err) => eprintln!("Could not authenticate as admin: {}", err), +    ///     Err((_, err)) => eprintln!("Could not authenticate as admin: {}", err),      /// }      /// #     Ok(())      /// # } | 
