diff options
| author | Robin Krahl <robin.krahl@ireas.org> | 2018-05-21 22:44:22 +0000 | 
|---|---|---|
| committer | Robin Krahl <robin.krahl@ireas.org> | 2018-05-22 00:44:45 +0200 | 
| commit | 57cab82dc3063cb6608aaf2ee937ad7af231c52a (patch) | |
| tree | e356de0f4db205d294d9ba495fa91203bf2ddc81 | |
| parent | ba716c0ba1fdcdfe824d84f04f7580a1c8501777 (diff) | |
| download | nitrokey-rs-57cab82dc3063cb6608aaf2ee937ad7af231c52a.tar.gz nitrokey-rs-57cab82dc3063cb6608aaf2ee937ad7af231c52a.tar.bz2 | |
Add support for change_admin_pin and change_user_pin
| -rw-r--r-- | TODO.md | 2 | ||||
| -rw-r--r-- | src/lib.rs | 76 | ||||
| -rw-r--r-- | src/tests/pro.rs | 48 | 
3 files changed, 123 insertions, 3 deletions
| @@ -5,8 +5,6 @@    - `NK_factory_reset`    - `NK_build_aes_key`    - `NK_unlock_user_password` -  - `NK_change_admin_PIN` -  - `NK_change_user_PIN`    - `NK_enable_password_safe`    - `NK_get_password_safe_slot_status`    - `NK_get_password_safe_slot_name` @@ -211,7 +211,6 @@ struct RawConfig {      pub user_password: bool,  } -#[derive(Debug)]  /// A Nitrokey device without user or admin authentication.  ///  /// Use [`connect`][] or [`connect_model`][] to obtain an instance.  If you @@ -250,6 +249,7 @@ struct RawConfig {  /// [`authenticate_user`]: #method.authenticate_user  /// [`connect`]: fn.connect.html  /// [`connect_model`]: fn.connect_model.html +#[derive(Debug)]  pub struct UnauthenticatedDevice {}  /// A Nitrokey device with user authentication. @@ -261,6 +261,7 @@ pub struct UnauthenticatedDevice {}  /// [`authenticate_admin`]: struct.UnauthenticatedDevice#method.authenticate_admin  /// [`device`]: #method.device  /// [`UnauthenticatedDevice`]: struct.UnauthenticatedDevice.html +#[derive(Debug)]  pub struct UserAuthenticatedDevice {      device: UnauthenticatedDevice,      temp_password: Vec<u8>, @@ -275,6 +276,7 @@ pub struct UserAuthenticatedDevice {  /// [`authenticate_admin`]: struct.UnauthenticatedDevice#method.authenticate_admin  /// [`device`]: #method.device  /// [`UnauthenticatedDevice`]: struct.UnauthenticatedDevice.html +#[derive(Debug)]  pub struct AdminAuthenticatedDevice {      device: UnauthenticatedDevice,      temp_password: Vec<u8>, @@ -634,6 +636,78 @@ pub trait Device {              return result_from_string(nitrokey_sys::NK_get_totp_code(slot, 0, 0, 0));          }      } + +    /// Changes the administrator PIN. +    /// +    /// # Errors +    ///  +    /// - [`InvalidString`][] if one of the provided passwords contains a null byte +    /// - [`WrongPassword`][] if the current admin password is wrong +    /// +    /// # Example +    /// +    /// ```no_run +    /// use nitrokey::Device; +    /// # use nitrokey::CommandError; +    /// +    /// # fn try_main() -> Result<(), CommandError> { +    /// let device = nitrokey::connect()?; +    /// match device.change_admin_pin("12345678", "12345679") { +    ///     CommandStatus::Success => println!("Updated admin PIN."), +    ///     CommandStatus::Error(err) => println!("Failed to update admin PIN: {:?}", err), +    /// }; +    /// #     Ok(()) +    /// # } +    /// ``` +    /// +    /// [`InvalidString`]: enum.CommandError.html#variant.InvalidString +    /// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword +    fn change_admin_pin(&self, current: &str, new: &str) -> CommandStatus { +        let current_string = CString::new(current); +        let new_string = CString::new(new); +        if current_string.is_err() || new_string.is_err() { +            return CommandStatus::Error(CommandError::InvalidString); +        } +        let current_string = current_string.unwrap(); +        let new_string = new_string.unwrap(); +        unsafe { CommandStatus::from(nitrokey_sys::NK_change_admin_PIN(current_string.as_ptr(), new_string.as_ptr())) } +    } + +    /// Changes the user PIN. +    /// +    /// # Errors +    ///  +    /// - [`InvalidString`][] if one of the provided passwords contains a null byte +    /// - [`WrongPassword`][] if the current user password is wrong +    /// +    /// # Example +    /// +    /// ```no_run +    /// use nitrokey::Device; +    /// # use nitrokey::CommandError; +    /// +    /// # fn try_main() -> Result<(), CommandError> { +    /// let device = nitrokey::connect()?; +    /// match device.change_user_pin("123456", "123457") { +    ///     CommandStatus::Success => println!("Updated admin PIN."), +    ///     CommandStatus::Error(err) => println!("Failed to update admin PIN: {:?}", err), +    /// }; +    /// #     Ok(()) +    /// # } +    /// ``` +    /// +    /// [`InvalidString`]: enum.CommandError.html#variant.InvalidString +    /// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword +    fn change_user_pin(&self, current: &str, new: &str) -> CommandStatus { +        let current_string = CString::new(current); +        let new_string = CString::new(new); +        if current_string.is_err() || new_string.is_err() { +            return CommandStatus::Error(CommandError::InvalidString); +        } +        let current_string = current_string.unwrap(); +        let new_string = new_string.unwrap(); +        unsafe { CommandStatus::from(nitrokey_sys::NK_change_user_PIN(current_string.as_ptr(), new_string.as_ptr())) } +    }  }  trait AuthenticatedDevice { diff --git a/src/tests/pro.rs b/src/tests/pro.rs index a23d42a..d2132f8 100644 --- a/src/tests/pro.rs +++ b/src/tests/pro.rs @@ -4,7 +4,9 @@ use {set_debug, AdminAuthenticatedDevice, CommandError, CommandStatus, Config, D       OtpMode, OtpSlotData, UnauthenticatedDevice};  static ADMIN_PASSWORD: &str = "12345678"; +static ADMIN_NEW_PASSWORD: &str = "1234567890";  static USER_PASSWORD: &str = "123456"; +static USER_NEW_PASSWORD: &str = "abcdefghij";  // test suite according to RFC 4226, Appendix D  static HOTP_SECRET: &str = "3132333435363738393031323334353637383930"; @@ -330,3 +332,49 @@ fn read_write_config() {      let get_config = admin.get_config().unwrap();      assert_eq!(config, get_config);  } + +#[test] +#[cfg_attr(not(feature = "test-pro"), ignore)] +fn change_user_pin() { +    let device = get_test_device(); +    let device = device.authenticate_user(USER_PASSWORD).unwrap().device(); +    let device = device.authenticate_user(USER_NEW_PASSWORD).unwrap_err().0; + +    let result = device.change_user_pin(USER_PASSWORD, USER_NEW_PASSWORD); +    assert_eq!(CommandStatus::Success, result); + +    let device = device.authenticate_user(USER_PASSWORD).unwrap_err().0; +    let device = device.authenticate_user(USER_NEW_PASSWORD).unwrap().device(); + +    let result = device.change_user_pin(USER_PASSWORD, USER_PASSWORD); +    assert_eq!(CommandStatus::Error(CommandError::WrongPassword), result); + +    let result = device.change_user_pin(USER_NEW_PASSWORD, USER_PASSWORD); +    assert_eq!(CommandStatus::Success, result); + +    let device = device.authenticate_user(USER_PASSWORD).unwrap().device(); +    device.authenticate_user(USER_NEW_PASSWORD).unwrap_err(); +} + +#[test] +#[cfg_attr(not(feature = "test-pro"), ignore)] +fn change_admin_pin() { +    let device = get_test_device(); +    let device = device.authenticate_admin(ADMIN_PASSWORD).unwrap().device(); +    let device = device.authenticate_admin(ADMIN_NEW_PASSWORD).unwrap_err().0; + +    let result = device.change_admin_pin(ADMIN_PASSWORD, ADMIN_NEW_PASSWORD); +    assert_eq!(CommandStatus::Success, result); + +    let device = device.authenticate_admin(ADMIN_PASSWORD).unwrap_err().0; +    let device = device.authenticate_admin(ADMIN_NEW_PASSWORD).unwrap().device(); + +    let result = device.change_admin_pin(ADMIN_PASSWORD, ADMIN_PASSWORD); +    assert_eq!(CommandStatus::Error(CommandError::WrongPassword), result); + +    let result = device.change_admin_pin(ADMIN_NEW_PASSWORD, ADMIN_PASSWORD); +    assert_eq!(CommandStatus::Success, result); + +    let device = device.authenticate_admin(ADMIN_PASSWORD).unwrap().device(); +    device.authenticate_admin(ADMIN_NEW_PASSWORD).unwrap_err(); +} | 
