diff options
Diffstat (limited to 'src/device.rs')
-rw-r--r-- | src/device.rs | 121 |
1 files changed, 71 insertions, 50 deletions
diff --git a/src/device.rs b/src/device.rs index ce45a50..ab90d3d 100644 --- a/src/device.rs +++ b/src/device.rs @@ -28,7 +28,7 @@ pub enum Model { /// Authentication with error handling: /// /// ```no_run -/// use nitrokey::{UnauthenticatedDevice, UserAuthenticatedDevice}; +/// use nitrokey::{Authenticate, UnauthenticatedDevice, UserAuthenticatedDevice}; /// # use nitrokey::CommandError; /// /// fn perform_user_task(device: &UserAuthenticatedDevice) {} @@ -51,8 +51,8 @@ pub enum Model { /// # } /// ``` /// -/// [`authenticate_admin`]: #method.authenticate_admin -/// [`authenticate_user`]: #method.authenticate_user +/// [`authenticate_admin`]: trait.Authenticate.html#method.authenticate_admin +/// [`authenticate_user`]: trait.Authenticate.html#method.authenticate_user /// [`connect`]: fn.connect.html /// [`connect_model`]: fn.connect_model.html #[derive(Debug)] @@ -64,7 +64,7 @@ pub struct UnauthenticatedDevice {} /// method on an [`UnauthenticatedDevice`][]. To get back to an /// unauthenticated device, use the [`device`][] method. /// -/// [`authenticate_admin`]: struct.UnauthenticatedDevice#method.authenticate_admin +/// [`authenticate_admin`]: trait.Authenticate.html#method.authenticate_admin /// [`device`]: #method.device /// [`UnauthenticatedDevice`]: struct.UnauthenticatedDevice.html #[derive(Debug)] @@ -79,7 +79,7 @@ pub struct UserAuthenticatedDevice { /// method on an [`UnauthenticatedDevice`][]. To get back to an /// unauthenticated device, use the [`device`][] method. /// -/// [`authenticate_admin`]: struct.UnauthenticatedDevice#method.authenticate_admin +/// [`authenticate_admin`]: trait.Authenticate.html#method.authenticate_admin /// [`device`]: #method.device /// [`UnauthenticatedDevice`]: struct.UnauthenticatedDevice.html #[derive(Debug)] @@ -350,38 +350,10 @@ pub trait Device { } } -trait AuthenticatedDevice { - fn new(device: UnauthenticatedDevice, temp_password: Vec<u8>) -> Self; -} - -impl UnauthenticatedDevice { - fn authenticate<D, T>( - self, - password: &str, - callback: T, - ) -> Result<D, (UnauthenticatedDevice, CommandError)> - where - D: AuthenticatedDevice, - T: Fn(*const i8, *const i8) -> c_int, - { - let temp_password = match generate_password(TEMPORARY_PASSWORD_LENGTH) { - Ok(pw) => pw, - Err(_) => return Err((self, CommandError::RngError)), - }; - let password = CString::new(password); - if password.is_err() { - return Err((self, CommandError::InvalidString)); - } - - let pw = password.unwrap(); - let password_ptr = pw.as_ptr(); - let temp_password_ptr = temp_password.as_ptr() as *const i8; - return match callback(password_ptr, temp_password_ptr) { - 0 => Ok(D::new(self, temp_password)), - rv => Err((self, CommandError::from(rv))), - }; - } - +/// Provides methods to authenticate as a user or as an admin using a PIN. The authenticated +/// methods will consume the current device instance. On success, they return the authenticated +/// device. Otherwise, they return the current unauthenticated device and the error code. +pub trait Authenticate { /// Performs user authentication. This method consumes the device. If /// successful, an authenticated device is returned. Otherwise, the /// current unauthenticated device and the error are returned. @@ -398,7 +370,7 @@ impl UnauthenticatedDevice { /// # Example /// /// ```no_run - /// use nitrokey::{UnauthenticatedDevice, UserAuthenticatedDevice}; + /// use nitrokey::{Authenticate, UnauthenticatedDevice, UserAuthenticatedDevice}; /// # use nitrokey::CommandError; /// /// fn perform_user_task(device: &UserAuthenticatedDevice) {} @@ -424,14 +396,12 @@ impl UnauthenticatedDevice { /// [`InvalidString`]: enum.CommandError.html#variant.InvalidString /// [`RngError`]: enum.CommandError.html#variant.RngError /// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword - pub fn authenticate_user( + fn authenticate_user( self, password: &str, - ) -> Result<UserAuthenticatedDevice, (UnauthenticatedDevice, CommandError)> { - return self.authenticate(password, |password_ptr, temp_password_ptr| unsafe { - nitrokey_sys::NK_user_authenticate(password_ptr, temp_password_ptr) - }); - } + ) -> Result<UserAuthenticatedDevice, (Self, CommandError)> + where + Self: Sized; /// Performs admin authentication. This method consumes the device. If /// successful, an authenticated device is returned. Otherwise, the @@ -449,7 +419,7 @@ impl UnauthenticatedDevice { /// # Example /// /// ```no_run - /// use nitrokey::{AdminAuthenticatedDevice, UnauthenticatedDevice}; + /// use nitrokey::{Authenticate, AdminAuthenticatedDevice, UnauthenticatedDevice}; /// # use nitrokey::CommandError; /// /// fn perform_admin_task(device: &AdminAuthenticatedDevice) {} @@ -475,10 +445,61 @@ impl UnauthenticatedDevice { /// [`InvalidString`]: enum.CommandError.html#variant.InvalidString /// [`RngError`]: enum.CommandError.html#variant.RngError /// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword - pub fn authenticate_admin( + fn authenticate_admin( + self, + password: &str, + ) -> Result<AdminAuthenticatedDevice, (Self, CommandError)> + where + Self: Sized; +} + +trait AuthenticatedDevice { + fn new(device: UnauthenticatedDevice, temp_password: Vec<u8>) -> Self; +} + +impl UnauthenticatedDevice { + fn authenticate<D, T>( + self, + password: &str, + callback: T, + ) -> Result<D, (UnauthenticatedDevice, CommandError)> + where + D: AuthenticatedDevice, + T: Fn(*const i8, *const i8) -> c_int, + { + let temp_password = match generate_password(TEMPORARY_PASSWORD_LENGTH) { + Ok(pw) => pw, + Err(_) => return Err((self, CommandError::RngError)), + }; + let password = CString::new(password); + if password.is_err() { + return Err((self, CommandError::InvalidString)); + } + + let pw = password.unwrap(); + let password_ptr = pw.as_ptr(); + let temp_password_ptr = temp_password.as_ptr() as *const i8; + return match callback(password_ptr, temp_password_ptr) { + 0 => Ok(D::new(self, temp_password)), + rv => Err((self, CommandError::from(rv))), + }; + } +} + +impl Authenticate for UnauthenticatedDevice { + fn authenticate_user( + self, + password: &str, + ) -> Result<UserAuthenticatedDevice, (Self, CommandError)> { + return self.authenticate(password, |password_ptr, temp_password_ptr| unsafe { + nitrokey_sys::NK_user_authenticate(password_ptr, temp_password_ptr) + }); + } + + fn authenticate_admin( self, password: &str, - ) -> Result<AdminAuthenticatedDevice, (UnauthenticatedDevice, CommandError)> { + ) -> Result<AdminAuthenticatedDevice, (Self, CommandError)> { return self.authenticate(password, |password_ptr, temp_password_ptr| unsafe { nitrokey_sys::NK_first_authenticate(password_ptr, temp_password_ptr) }); @@ -521,7 +542,7 @@ impl GenerateOtp for UserAuthenticatedDevice { /// # Example /// /// ```no_run - /// use nitrokey::{Device, GenerateOtp}; + /// use nitrokey::{Authenticate, GenerateOtp}; /// # use nitrokey::CommandError; /// /// # fn try_main() -> Result<(), CommandError> { @@ -562,7 +583,7 @@ impl GenerateOtp for UserAuthenticatedDevice { /// # Example /// /// ```no_run - /// use nitrokey::{Device, GenerateOtp}; + /// use nitrokey::{Authenticate, GenerateOtp}; /// # use nitrokey::CommandError; /// /// # fn try_main() -> Result<(), CommandError> { @@ -623,7 +644,7 @@ impl AdminAuthenticatedDevice { /// # Example /// /// ```no_run - /// use nitrokey::Config; + /// use nitrokey::{Authenticate, Config}; /// # use nitrokey::CommandError; /// /// # fn try_main() -> Result<(), CommandError> { |