diff options
| author | Robin Krahl <robin.krahl@ireas.org> | 2018-05-28 21:03:26 +0000 | 
|---|---|---|
| committer | Robin Krahl <robin.krahl@ireas.org> | 2018-05-28 23:04:03 +0200 | 
| commit | fa472112a82e2eca052cd8ed0a09c2849a665f67 (patch) | |
| tree | 6ef4ca04c86f605e5dafa26e9191c3cb06a6a859 | |
| parent | 8f7eb1679fa988ad97b0e6dbe0ef5d1edef18351 (diff) | |
| download | nitrokey-rs-fa472112a82e2eca052cd8ed0a09c2849a665f67.tar.gz nitrokey-rs-fa472112a82e2eca052cd8ed0a09c2849a665f67.tar.bz2 | |
Move Admin, User and Authenticate to auth module
| -rw-r--r-- | src/auth.rs | 389 | ||||
| -rw-r--r-- | src/device.rs | 290 | ||||
| -rw-r--r-- | src/lib.rs | 6 | ||||
| -rw-r--r-- | src/misc.rs | 99 | 
4 files changed, 394 insertions, 390 deletions
| diff --git a/src/auth.rs b/src/auth.rs new file mode 100644 index 0000000..80abbc0 --- /dev/null +++ b/src/auth.rs @@ -0,0 +1,389 @@ +use config::{Config, RawConfig}; +use device::{Device, DeviceWrapper, Pro}; +use nitrokey_sys; +use std::ffi::CString; +use std::ops::Deref; +use std::os::raw::c_int; +use otp::{ConfigureOtp, GenerateOtp, OtpMode, OtpSlotData, RawOtpSlotData}; +use util::{generate_password, result_from_string, CommandError, CommandStatus}; + +static TEMPORARY_PASSWORD_LENGTH: usize = 25; + +/// 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. +    /// +    /// This method generates a random temporary password that is used for all operations that +    /// require user access. +    /// +    /// # Errors +    /// +    /// - [`InvalidString`][] if the provided user password contains a null byte +    /// - [`RngError`][] if the generation of the temporary password failed +    /// - [`WrongPassword`][] if the provided user password is wrong +    /// +    /// # Example +    /// +    /// ```no_run +    /// use nitrokey::{Authenticate, DeviceWrapper, User}; +    /// # use nitrokey::CommandError; +    /// +    /// fn perform_user_task(device: &User<DeviceWrapper>) {} +    /// fn perform_other_task(device: &DeviceWrapper) {} +    /// +    /// # fn try_main() -> Result<(), CommandError> { +    /// let device = nitrokey::connect()?; +    /// let device = match device.authenticate_user("123456") { +    ///     Ok(user) => { +    ///         perform_user_task(&user); +    ///         user.device() +    ///     }, +    ///     Err((device, err)) => { +    ///         println!("Could not authenticate as user: {:?}", err); +    ///         device +    ///     }, +    /// }; +    /// perform_other_task(&device); +    /// #     Ok(()) +    /// # } +    /// ``` +    /// +    /// [`InvalidString`]: enum.CommandError.html#variant.InvalidString +    /// [`RngError`]: enum.CommandError.html#variant.RngError +    /// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword +    fn authenticate_user(self, password: &str) -> Result<User<Self>, (Self, CommandError)> +    where +        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 +    /// error are returned. +    /// +    /// This method generates a random temporary password that is used for all operations that +    /// require admin access. +    /// +    /// # Errors +    /// +    /// - [`InvalidString`][] if the provided admin password contains a null byte +    /// - [`RngError`][] if the generation of the temporary password failed +    /// - [`WrongPassword`][] if the provided admin password is wrong +    /// +    /// # Example +    /// +    /// ```no_run +    /// use nitrokey::{Authenticate, Admin, DeviceWrapper}; +    /// # use nitrokey::CommandError; +    /// +    /// fn perform_admin_task(device: &Admin<DeviceWrapper>) {} +    /// fn perform_other_task(device: &DeviceWrapper) {} +    /// +    /// # fn try_main() -> Result<(), CommandError> { +    /// let device = nitrokey::connect()?; +    /// let device = match device.authenticate_admin("123456") { +    ///     Ok(admin) => { +    ///         perform_admin_task(&admin); +    ///         admin.device() +    ///     }, +    ///     Err((device, err)) => { +    ///         println!("Could not authenticate as admin: {:?}", err); +    ///         device +    ///     }, +    /// }; +    /// perform_other_task(&device); +    /// #     Ok(()) +    /// # } +    /// ``` +    /// +    /// [`InvalidString`]: enum.CommandError.html#variant.InvalidString +    /// [`RngError`]: enum.CommandError.html#variant.RngError +    /// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword +    fn authenticate_admin(self, password: &str) -> Result<Admin<Self>, (Self, CommandError)> +    where +        Self: Device + Sized; +} + +trait AuthenticatedDevice<T> { +    fn new(device: T, temp_password: Vec<u8>) -> Self; +} + +/// A Nitrokey device with user authentication. +/// +/// To obtain an instance of this struct, use the [`authenticate_user`][] method from the +/// [`Authenticate`][] trait.  To get back to an unauthenticated device, use the [`device`][] +/// method. +/// +/// [`Authenticate`]: trait.Authenticate.html +/// [`authenticate_admin`]: trait.Authenticate.html#method.authenticate_admin +/// [`device`]: #method.device +#[derive(Debug)] +pub struct User<T: Device> { +    device: T, +    temp_password: Vec<u8>, +} + +/// A Nitrokey device with admin authentication. +/// +/// To obtain an instance of this struct, use the [`authenticate_admin`][] method from the +/// [`Authenticate`][] trait.  To get back to an unauthenticated device, use the [`device`][] +/// method. +/// +/// [`Authenticate`]: trait.Authenticate.html +/// [`authenticate_admin`]: trait.Authenticate.html#method.authenticate_admin +/// [`device`]: #method.device +#[derive(Debug)] +pub struct Admin<T: Device> { +    device: T, +    temp_password: Vec<u8>, +} + +fn authenticate<D, A, T>(device: D, password: &str, callback: T) -> Result<A, (D, CommandError)> +where +    D: Device, +    A: AuthenticatedDevice<D>, +    T: Fn(*const i8, *const i8) -> c_int, +{ +    let temp_password = match generate_password(TEMPORARY_PASSWORD_LENGTH) { +        Ok(pw) => pw, +        Err(_) => return Err((device, CommandError::RngError)), +    }; +    let password = CString::new(password); +    if password.is_err() { +        return Err((device, 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(A::new(device, temp_password)), +        rv => Err((device, CommandError::from(rv))), +    }; +} + +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> Deref for User<T> { +    type Target = T; + +    fn deref(&self) -> &Self::Target { +        &self.device +    } +} + +impl<T: Device> GenerateOtp for User<T> { +    fn get_hotp_code(&self, slot: u8) -> Result<String, CommandError> { +        unsafe { +            let temp_password_ptr = self.temp_password.as_ptr() as *const i8; +            return result_from_string(nitrokey_sys::NK_get_hotp_code_PIN(slot, temp_password_ptr)); +        } +    } + +    fn get_totp_code(&self, slot: u8) -> Result<String, CommandError> { +        unsafe { +            let temp_password_ptr = self.temp_password.as_ptr() as *const i8; +            return result_from_string(nitrokey_sys::NK_get_totp_code_PIN( +                slot, +                0, +                0, +                0, +                temp_password_ptr, +            )); +        } +    } +} + +impl<T: Device> AuthenticatedDevice<T> for User<T> { +    fn new(device: T, temp_password: Vec<u8>) -> Self { +        User { +            device, +            temp_password, +        } +    } +} + +impl<T: Device> Deref for Admin<T> { +    type Target = T; + +    fn deref(&self) -> &Self::Target { +        &self.device +    } +} + +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 +    /// +    /// - [`InvalidSlot`][] if the provided numlock, capslock or scrolllock slot is larger than two +    /// +    /// # Example +    /// +    /// ```no_run +    /// use nitrokey::{Authenticate, Config}; +    /// # use nitrokey::CommandError; +    /// +    /// # fn try_main() -> Result<(), CommandError> { +    /// let device = nitrokey::connect()?; +    /// let config = Config::new(None, None, None, false); +    /// match device.authenticate_admin("12345678") { +    ///     Ok(admin) => { +    ///         admin.write_config(config); +    ///         () +    ///     }, +    ///     Err((_, err)) => println!("Could not authenticate as admin: {:?}", err), +    /// }; +    /// #     Ok(()) +    /// # } +    /// ``` +    /// +    /// [`InvalidSlot`]: enum.CommandError.html#variant.InvalidSlot +    pub fn write_config(&self, config: Config) -> CommandStatus { +        let raw_config = match RawConfig::try_from(config) { +            Ok(raw_config) => raw_config, +            Err(err) => return CommandStatus::Error(err), +        }; +        unsafe { +            let rv = nitrokey_sys::NK_write_config( +                raw_config.numlock, +                raw_config.capslock, +                raw_config.scrollock, +                raw_config.user_password, +                false, +                self.temp_password.as_ptr() as *const i8, +            ); +            return CommandStatus::from(rv); +        } +    } + +    fn write_otp_slot<C>(&self, data: OtpSlotData, callback: C) -> CommandStatus +    where +        C: Fn(RawOtpSlotData, *const i8) -> c_int, +    { +        let raw_data = match RawOtpSlotData::new(data) { +            Ok(raw_data) => raw_data, +            Err(err) => return CommandStatus::Error(err), +        }; +        let temp_password_ptr = self.temp_password.as_ptr() as *const i8; +        let rv = callback(raw_data, temp_password_ptr); +        return CommandStatus::from(rv); +    } +} + +impl<T: Device> ConfigureOtp for Admin<T> { +    fn write_hotp_slot(&self, data: OtpSlotData, counter: u64) -> CommandStatus { +        return self.write_otp_slot(data, |raw_data: RawOtpSlotData, temp_password_ptr| unsafe { +            nitrokey_sys::NK_write_hotp_slot( +                raw_data.number, +                raw_data.name.as_ptr(), +                raw_data.secret.as_ptr(), +                counter, +                raw_data.mode == OtpMode::EightDigits, +                raw_data.use_enter, +                raw_data.use_token_id, +                raw_data.token_id.as_ptr(), +                temp_password_ptr, +            ) +        }); +    } + +    fn write_totp_slot(&self, data: OtpSlotData, time_window: u16) -> CommandStatus { +        return self.write_otp_slot(data, |raw_data: RawOtpSlotData, temp_password_ptr| unsafe { +            nitrokey_sys::NK_write_totp_slot( +                raw_data.number, +                raw_data.name.as_ptr(), +                raw_data.secret.as_ptr(), +                time_window, +                raw_data.mode == OtpMode::EightDigits, +                raw_data.use_enter, +                raw_data.use_token_id, +                raw_data.token_id.as_ptr(), +                temp_password_ptr, +            ) +        }); +    } + +    fn erase_hotp_slot(&self, slot: u8) -> CommandStatus { +        let temp_password_ptr = self.temp_password.as_ptr() as *const i8; +        unsafe { CommandStatus::from(nitrokey_sys::NK_erase_hotp_slot(slot, temp_password_ptr)) } +    } + +    fn erase_totp_slot(&self, slot: u8) -> CommandStatus { +        let temp_password_ptr = self.temp_password.as_ptr() as *const i8; +        unsafe { CommandStatus::from(nitrokey_sys::NK_erase_totp_slot(slot, temp_password_ptr)) } +    } +} + +impl<T: Device> AuthenticatedDevice<T> for Admin<T> { +    fn new(device: T, temp_password: Vec<u8>) -> Self { +        Admin { +            device, +            temp_password, +        } +    } +} + +impl Authenticate for DeviceWrapper { +    fn authenticate_user(self, password: &str) -> Result<User<Self>, (Self, CommandError)> { +        match self { +            DeviceWrapper::Storage(_) => panic!("..."), +            DeviceWrapper::Pro(pro) => { +                let result = pro.authenticate_user(password); +                match result { +                    Ok(user) => Ok(User::new( +                        DeviceWrapper::Pro(user.device), +                        user.temp_password, +                    )), +                    Err((pro, err)) => Err((DeviceWrapper::Pro(pro), err)), +                } +            } +        } +    } + +    fn authenticate_admin(self, password: &str) -> Result<Admin<Self>, (Self, CommandError)> { +        match self { +            DeviceWrapper::Storage(_) => panic!("..."), +            DeviceWrapper::Pro(pro) => { +                let result = pro.authenticate_admin(password); +                match result { +                    Ok(admin) => Ok(Admin::new( +                        DeviceWrapper::Pro(admin.device), +                        admin.temp_password, +                    )), +                    Err((pro, err)) => Err((DeviceWrapper::Pro(pro), err)), +                } +            } +        } +    } +} + +impl Authenticate for Pro { +    fn authenticate_user(self, password: &str) -> Result<User<Self>, (Self, CommandError)> { +        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, CommandError)> { +        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 8f7dc00..684f64a 100644 --- a/src/device.rs +++ b/src/device.rs @@ -2,13 +2,8 @@ use config::{Config, RawConfig};  use libc;  use nitrokey_sys;  use std::ffi::CString; -use std::ops::Deref; -use std::os::raw::c_int; -use misc::Authenticate; -use otp::{ConfigureOtp, GenerateOtp, OtpMode, OtpSlotData, RawOtpSlotData}; -use util::{generate_password, get_last_error, result_from_string, CommandError, CommandStatus}; - -static TEMPORARY_PASSWORD_LENGTH: usize = 25; +use otp::GenerateOtp; +use util::{get_last_error, result_from_string, CommandError, CommandStatus};  /// Available Nitrokey models.  #[derive(Debug, PartialEq)] @@ -106,36 +101,6 @@ pub enum DeviceWrapper {  #[derive(Debug)]  pub struct Pro {} -/// A Nitrokey device with user authentication. -/// -/// To obtain an instance of this struct, use the [`authenticate_user`][] method from the -/// [`Authenticate`][] trait.  To get back to an unauthenticated device, use the [`device`][] -/// method. -/// -/// [`Authenticate`]: trait.Authenticate.html -/// [`authenticate_admin`]: trait.Authenticate.html#method.authenticate_admin -/// [`device`]: #method.device -#[derive(Debug)] -pub struct User<T: Device> { -    device: T, -    temp_password: Vec<u8>, -} - -/// A Nitrokey device with admin authentication. -/// -/// To obtain an instance of this struct, use the [`authenticate_admin`][] method from the -/// [`Authenticate`][] trait.  To get back to an unauthenticated device, use the [`device`][] -/// method. -/// -/// [`Authenticate`]: trait.Authenticate.html -/// [`authenticate_admin`]: trait.Authenticate.html#method.authenticate_admin -/// [`device`]: #method.device -#[derive(Debug)] -pub struct Admin<T: Device> { -    device: T, -    temp_password: Vec<u8>, -} -  /// A Nitrokey device.  ///  /// This trait provides the commands that can be executed without authentication and that are @@ -360,10 +325,6 @@ pub trait Device: GenerateOtp {      }  } -trait AuthenticatedDevice<T> { -    fn new(device: T, temp_password: Vec<u8>) -> Self; -} -  /// Connects to a Nitrokey device.  This method can be used to connect to any connected device,  /// both a Nitrokey Pro and a Nitrokey Storage.  /// @@ -433,40 +394,6 @@ impl GenerateOtp for DeviceWrapper {  impl Device for DeviceWrapper {} -impl Authenticate for DeviceWrapper { -    fn authenticate_user(self, password: &str) -> Result<User<Self>, (Self, CommandError)> { -        match self { -            DeviceWrapper::Storage(_) => panic!("..."), -            DeviceWrapper::Pro(pro) => { -                let result = pro.authenticate_user(password); -                match result { -                    Ok(user) => Ok(User::new( -                        DeviceWrapper::Pro(user.device), -                        user.temp_password, -                    )), -                    Err((pro, err)) => Err((DeviceWrapper::Pro(pro), err)), -                } -            } -        } -    } - -    fn authenticate_admin(self, password: &str) -> Result<Admin<Self>, (Self, CommandError)> { -        match self { -            DeviceWrapper::Storage(_) => panic!("..."), -            DeviceWrapper::Pro(pro) => { -                let result = pro.authenticate_admin(password); -                match result { -                    Ok(admin) => Ok(Admin::new( -                        DeviceWrapper::Pro(admin.device), -                        admin.temp_password, -                    )), -                    Err((pro, err)) => Err((DeviceWrapper::Pro(pro), err)), -                } -            } -        } -    } -} -  impl Pro {      pub fn connect() -> Result<Pro, CommandError> {          // TODO: maybe Option instead of Result? @@ -475,43 +402,6 @@ impl Pro {              false => Err(CommandError::Unknown),          }      } - -    fn authenticate<D, T>(self, password: &str, callback: T) -> Result<D, (Self, CommandError)> -    where -        D: AuthenticatedDevice<Pro>, -        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 Pro { -    fn authenticate_user(self, password: &str) -> Result<User<Self>, (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<Admin<Self>, (Self, CommandError)> { -        return self.authenticate(password, |password_ptr, temp_password_ptr| unsafe { -            nitrokey_sys::NK_first_authenticate(password_ptr, temp_password_ptr) -        }); -    }  }  impl Drop for Pro { @@ -525,179 +415,3 @@ impl Drop for Pro {  impl Device for Pro {}  impl GenerateOtp for Pro {} - -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> Deref for User<T> { -    type Target = T; - -    fn deref(&self) -> &Self::Target { -        &self.device -    } -} - -impl<T: Device> GenerateOtp for User<T> { -    fn get_hotp_code(&self, slot: u8) -> Result<String, CommandError> { -        unsafe { -            let temp_password_ptr = self.temp_password.as_ptr() as *const i8; -            return result_from_string(nitrokey_sys::NK_get_hotp_code_PIN(slot, temp_password_ptr)); -        } -    } - -    fn get_totp_code(&self, slot: u8) -> Result<String, CommandError> { -        unsafe { -            let temp_password_ptr = self.temp_password.as_ptr() as *const i8; -            return result_from_string(nitrokey_sys::NK_get_totp_code_PIN( -                slot, -                0, -                0, -                0, -                temp_password_ptr, -            )); -        } -    } -} - -impl<T: Device> AuthenticatedDevice<T> for User<T> { -    fn new(device: T, temp_password: Vec<u8>) -> Self { -        User { -            device, -            temp_password, -        } -    } -} - -impl<T: Device> Deref for Admin<T> { -    type Target = T; - -    fn deref(&self) -> &Self::Target { -        &self.device -    } -} - -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 -    /// -    /// - [`InvalidSlot`][] if the provided numlock, capslock or scrolllock slot is larger than two -    /// -    /// # Example -    /// -    /// ```no_run -    /// use nitrokey::{Authenticate, Config}; -    /// # use nitrokey::CommandError; -    /// -    /// # fn try_main() -> Result<(), CommandError> { -    /// let device = nitrokey::connect()?; -    /// let config = Config::new(None, None, None, false); -    /// match device.authenticate_admin("12345678") { -    ///     Ok(admin) => { -    ///         admin.write_config(config); -    ///         () -    ///     }, -    ///     Err((_, err)) => println!("Could not authenticate as admin: {:?}", err), -    /// }; -    /// #     Ok(()) -    /// # } -    /// ``` -    /// -    /// [`InvalidSlot`]: enum.CommandError.html#variant.InvalidSlot -    pub fn write_config(&self, config: Config) -> CommandStatus { -        let raw_config = match RawConfig::try_from(config) { -            Ok(raw_config) => raw_config, -            Err(err) => return CommandStatus::Error(err), -        }; -        unsafe { -            let rv = nitrokey_sys::NK_write_config( -                raw_config.numlock, -                raw_config.capslock, -                raw_config.scrollock, -                raw_config.user_password, -                false, -                self.temp_password.as_ptr() as *const i8, -            ); -            return CommandStatus::from(rv); -        } -    } - -    fn write_otp_slot<C>(&self, data: OtpSlotData, callback: C) -> CommandStatus -    where -        C: Fn(RawOtpSlotData, *const i8) -> c_int, -    { -        let raw_data = match RawOtpSlotData::new(data) { -            Ok(raw_data) => raw_data, -            Err(err) => return CommandStatus::Error(err), -        }; -        let temp_password_ptr = self.temp_password.as_ptr() as *const i8; -        let rv = callback(raw_data, temp_password_ptr); -        return CommandStatus::from(rv); -    } -} - -impl<T: Device> ConfigureOtp for Admin<T> { -    fn write_hotp_slot(&self, data: OtpSlotData, counter: u64) -> CommandStatus { -        return self.write_otp_slot(data, |raw_data: RawOtpSlotData, temp_password_ptr| unsafe { -            nitrokey_sys::NK_write_hotp_slot( -                raw_data.number, -                raw_data.name.as_ptr(), -                raw_data.secret.as_ptr(), -                counter, -                raw_data.mode == OtpMode::EightDigits, -                raw_data.use_enter, -                raw_data.use_token_id, -                raw_data.token_id.as_ptr(), -                temp_password_ptr, -            ) -        }); -    } - -    fn write_totp_slot(&self, data: OtpSlotData, time_window: u16) -> CommandStatus { -        return self.write_otp_slot(data, |raw_data: RawOtpSlotData, temp_password_ptr| unsafe { -            nitrokey_sys::NK_write_totp_slot( -                raw_data.number, -                raw_data.name.as_ptr(), -                raw_data.secret.as_ptr(), -                time_window, -                raw_data.mode == OtpMode::EightDigits, -                raw_data.use_enter, -                raw_data.use_token_id, -                raw_data.token_id.as_ptr(), -                temp_password_ptr, -            ) -        }); -    } - -    fn erase_hotp_slot(&self, slot: u8) -> CommandStatus { -        let temp_password_ptr = self.temp_password.as_ptr() as *const i8; -        unsafe { CommandStatus::from(nitrokey_sys::NK_erase_hotp_slot(slot, temp_password_ptr)) } -    } - -    fn erase_totp_slot(&self, slot: u8) -> CommandStatus { -        let temp_password_ptr = self.temp_password.as_ptr() as *const i8; -        unsafe { CommandStatus::from(nitrokey_sys::NK_erase_totp_slot(slot, temp_password_ptr)) } -    } -} - -impl<T: Device> AuthenticatedDevice<T> for Admin<T> { -    fn new(device: T, temp_password: Vec<u8>) -> Self { -        Admin { -            device, -            temp_password, -        } -    } -} @@ -87,17 +87,17 @@ extern crate libc;  extern crate nitrokey_sys;  extern crate rand; +mod auth;  mod config;  mod device; -mod misc;  mod otp;  mod util;  #[cfg(test)]  mod tests;  pub use config::Config; -pub use device::{connect, Admin, Device, DeviceWrapper, Pro, User}; -pub use misc::Authenticate; +pub use device::{connect, Device, DeviceWrapper, Pro}; +pub use auth::{Admin, Authenticate, User};  pub use otp::{ConfigureOtp, GenerateOtp, OtpMode, OtpSlotData};  pub use util::{CommandError, CommandStatus, LogLevel}; diff --git a/src/misc.rs b/src/misc.rs deleted file mode 100644 index 16d5884..0000000 --- a/src/misc.rs +++ /dev/null @@ -1,99 +0,0 @@ -use device::{Admin, Device, User}; -use util::CommandError; - -/// 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. -    /// -    /// This method generates a random temporary password that is used for all operations that -    /// require user access. -    /// -    /// # Errors -    /// -    /// - [`InvalidString`][] if the provided user password contains a null byte -    /// - [`RngError`][] if the generation of the temporary password failed -    /// - [`WrongPassword`][] if the provided user password is wrong -    /// -    /// # Example -    /// -    /// ```no_run -    /// use nitrokey::{Authenticate, DeviceWrapper, User}; -    /// # use nitrokey::CommandError; -    /// -    /// fn perform_user_task(device: &User<DeviceWrapper>) {} -    /// fn perform_other_task(device: &DeviceWrapper) {} -    /// -    /// # fn try_main() -> Result<(), CommandError> { -    /// let device = nitrokey::connect()?; -    /// let device = match device.authenticate_user("123456") { -    ///     Ok(user) => { -    ///         perform_user_task(&user); -    ///         user.device() -    ///     }, -    ///     Err((device, err)) => { -    ///         println!("Could not authenticate as user: {:?}", err); -    ///         device -    ///     }, -    /// }; -    /// perform_other_task(&device); -    /// #     Ok(()) -    /// # } -    /// ``` -    /// -    /// [`InvalidString`]: enum.CommandError.html#variant.InvalidString -    /// [`RngError`]: enum.CommandError.html#variant.RngError -    /// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword -    fn authenticate_user(self, password: &str) -> Result<User<Self>, (Self, CommandError)> -    where -        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 -    /// error are returned. -    /// -    /// This method generates a random temporary password that is used for all operations that -    /// require admin access. -    /// -    /// # Errors -    /// -    /// - [`InvalidString`][] if the provided admin password contains a null byte -    /// - [`RngError`][] if the generation of the temporary password failed -    /// - [`WrongPassword`][] if the provided admin password is wrong -    /// -    /// # Example -    /// -    /// ```no_run -    /// use nitrokey::{Authenticate, Admin, DeviceWrapper}; -    /// # use nitrokey::CommandError; -    /// -    /// fn perform_admin_task(device: &Admin<DeviceWrapper>) {} -    /// fn perform_other_task(device: &DeviceWrapper) {} -    /// -    /// # fn try_main() -> Result<(), CommandError> { -    /// let device = nitrokey::connect()?; -    /// let device = match device.authenticate_admin("123456") { -    ///     Ok(admin) => { -    ///         perform_admin_task(&admin); -    ///         admin.device() -    ///     }, -    ///     Err((device, err)) => { -    ///         println!("Could not authenticate as admin: {:?}", err); -    ///         device -    ///     }, -    /// }; -    /// perform_other_task(&device); -    /// #     Ok(()) -    /// # } -    /// ``` -    /// -    /// [`InvalidString`]: enum.CommandError.html#variant.InvalidString -    /// [`RngError`]: enum.CommandError.html#variant.RngError -    /// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword -    fn authenticate_admin(self, password: &str) -> Result<Admin<Self>, (Self, CommandError)> -    where -        Self: Device + Sized; -} | 
