diff options
author | Daniel Mueller <deso@posteo.net> | 2020-04-04 14:39:19 -0700 |
---|---|---|
committer | Daniel Mueller <deso@posteo.net> | 2020-04-04 14:39:19 -0700 |
commit | d0d9683df8398696147e7ee1fcffb2e4e957008c (patch) | |
tree | 4baa76712a76f4d072ee3936c07956580b230820 /nitrokey/src/pws.rs | |
parent | 203e691f46d591a2cc8acdfd850fa9f5b0fb8a98 (diff) | |
download | nitrocli-d0d9683df8398696147e7ee1fcffb2e4e957008c.tar.gz nitrocli-d0d9683df8398696147e7ee1fcffb2e4e957008c.tar.bz2 |
Remove vendored dependencies
While it appears that by now we actually can get successful builds
without Cargo insisting on Internet access by virtue of using the
--frozen flag, maintaining vendored dependencies is somewhat of a pain
point. This state will also get worse with upcoming changes that replace
argparse in favor of structopt and pull in a slew of new dependencies by
doing so. Then there is also the repository structure aspect, which is
non-standard due to the way we vendor dependencies and a potential
source of confusion.
In order to fix these problems, this change removes all the vendored
dependencies we have.
Delete subrepo argparse/:argparse
Delete subrepo base32/:base32
Delete subrepo cc/:cc
Delete subrepo cfg-if/:cfg-if
Delete subrepo getrandom/:getrandom
Delete subrepo lazy-static/:lazy-static
Delete subrepo libc/:libc
Delete subrepo nitrokey-sys/:nitrokey-sys
Delete subrepo nitrokey/:nitrokey
Delete subrepo rand/:rand
Diffstat (limited to 'nitrokey/src/pws.rs')
-rw-r--r-- | nitrokey/src/pws.rs | 391 |
1 files changed, 0 insertions, 391 deletions
diff --git a/nitrokey/src/pws.rs b/nitrokey/src/pws.rs deleted file mode 100644 index 3398deb..0000000 --- a/nitrokey/src/pws.rs +++ /dev/null @@ -1,391 +0,0 @@ -// Copyright (C) 2018-2019 Robin Krahl <robin.krahl@ireas.org> -// SPDX-License-Identifier: MIT - -use libc; -use nitrokey_sys; - -use crate::device::{Device, DeviceWrapper, Pro, Storage}; -use crate::error::{CommandError, Error}; -use crate::util::{get_command_result, get_cstring, get_last_error, result_from_string}; - -/// The number of slots in a [`PasswordSafe`][]. -/// -/// [`PasswordSafe`]: struct.PasswordSafe.html -pub const SLOT_COUNT: u8 = 16; - -/// A password safe on a Nitrokey device. -/// -/// The password safe stores a tuple consisting of a name, a login and a password on a slot. The -/// number of available slots is [`SLOT_COUNT`][]. The slots are addressed starting with zero. To -/// retrieve a password safe from a Nitrokey device, use the [`get_password_safe`][] method from -/// the [`GetPasswordSafe`][] trait. Note that the device must live at least as long as the -/// password safe. -/// -/// Once the password safe has been unlocked, it can be accessed without a password. Therefore it -/// is mandatory to call [`lock`][] on the corresponding device after the password store is used. -/// As this command may have side effects on the Nitrokey Storage, it cannot be called -/// automatically once the password safe is destroyed. -/// -/// # Examples -/// -/// Open a password safe and access a password: -/// -/// ```no_run -/// use nitrokey::{Device, GetPasswordSafe, PasswordSafe}; -/// # use nitrokey::Error; -/// -/// fn use_password_safe(pws: &PasswordSafe) -> Result<(), Error> { -/// let name = pws.get_slot_name(0)?; -/// let login = pws.get_slot_login(0)?; -/// let password = pws.get_slot_login(0)?; -/// println!("Credentials for {}: login {}, password {}", name, login, password); -/// Ok(()) -/// } -/// -/// # fn try_main() -> Result<(), Error> { -/// let mut manager = nitrokey::take()?; -/// let mut device = manager.connect()?; -/// let pws = device.get_password_safe("123456")?; -/// use_password_safe(&pws); -/// drop(pws); -/// device.lock()?; -/// # Ok(()) -/// # } -/// ``` -/// -/// [`SLOT_COUNT`]: constant.SLOT_COUNT.html -/// [`get_password_safe`]: trait.GetPasswordSafe.html#method.get_password_safe -/// [`lock`]: trait.Device.html#method.lock -/// [`GetPasswordSafe`]: trait.GetPasswordSafe.html -#[derive(Debug)] -pub struct PasswordSafe<'a, 'b> { - _device: &'a dyn Device<'b>, -} - -/// Provides access to a [`PasswordSafe`][]. -/// -/// The device that implements this trait must always live at least as long as a password safe -/// retrieved from it. -/// -/// [`PasswordSafe`]: struct.PasswordSafe.html -pub trait GetPasswordSafe<'a> { - /// Enables and returns the password safe. - /// - /// The underlying device must always live at least as long as a password safe retrieved from - /// it. It is mandatory to lock the underlying device using [`lock`][] after the password safe - /// has been used. Otherwise, other applications can access the password store without - /// authentication. - /// - /// If this method returns an `AesDecryptionFailed` (Nitrokey Pro) or `Unknown` (Nitrokey - /// Storage) error, the AES data object on the smart card could not be accessed. This problem - /// occurs after a factory reset using `gpg --card-edit` and can be fixed using the - /// [`Device::build_aes_key`][] command. - /// - /// # Errors - /// - /// - [`AesDecryptionFailed`][] if the secret for the password safe could not be decrypted - /// (Nitrokey Pro only) - /// - [`InvalidString`][] if one of the provided passwords contains a null byte - /// - [`Unknown`][] if the secret for the password safe could not be decrypted (Nitrokey - /// Storage only) - /// - [`WrongPassword`][] if the current user password is wrong - /// - /// # Example - /// - /// ```no_run - /// use nitrokey::{Device, GetPasswordSafe, PasswordSafe}; - /// # use nitrokey::Error; - /// - /// fn use_password_safe(pws: &PasswordSafe) {} - /// - /// # fn try_main() -> Result<(), Error> { - /// let mut manager = nitrokey::take()?; - /// let mut device = manager.connect()?; - /// match device.get_password_safe("123456") { - /// Ok(pws) => { - /// use_password_safe(&pws); - /// }, - /// Err(err) => eprintln!("Could not open the password safe: {}", err), - /// }; - /// device.lock()?; - /// # Ok(()) - /// # } - /// ``` - /// - /// [`device`]: struct.PasswordSafe.html#method.device - /// [`lock`]: trait.Device.html#method.lock - /// [`AesDecryptionFailed`]: enum.CommandError.html#variant.AesDecryptionFailed - /// [`Device::build_aes_key`]: trait.Device.html#method.build_aes_key - /// [`InvalidString`]: enum.LibraryError.html#variant.InvalidString - /// [`Unknown`]: enum.CommandError.html#variant.Unknown - /// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword - fn get_password_safe(&mut self, user_pin: &str) -> Result<PasswordSafe<'_, 'a>, Error>; -} - -fn get_password_safe<'a, 'b>( - device: &'a dyn Device<'b>, - user_pin: &str, -) -> Result<PasswordSafe<'a, 'b>, Error> { - let user_pin_string = get_cstring(user_pin)?; - get_command_result(unsafe { nitrokey_sys::NK_enable_password_safe(user_pin_string.as_ptr()) }) - .map(|_| PasswordSafe { _device: device }) -} - -fn get_pws_result(s: String) -> Result<String, Error> { - if s.is_empty() { - Err(CommandError::SlotNotProgrammed.into()) - } else { - Ok(s) - } -} - -impl<'a, 'b> PasswordSafe<'a, 'b> { - /// Returns the status of all password slots. - /// - /// The status indicates whether a slot is programmed or not. - /// - /// # Example - /// - /// ```no_run - /// use nitrokey::{GetPasswordSafe, SLOT_COUNT}; - /// # use nitrokey::Error; - /// - /// # fn try_main() -> Result<(), Error> { - /// let mut manager = nitrokey::take()?; - /// let mut device = manager.connect()?; - /// let pws = device.get_password_safe("123456")?; - /// pws.get_slot_status()?.iter().enumerate().for_each(|(slot, programmed)| { - /// let status = match *programmed { - /// true => "programmed", - /// false => "not programmed", - /// }; - /// println!("Slot {}: {}", slot, status); - /// }); - /// # Ok(()) - /// # } - /// ``` - pub fn get_slot_status(&self) -> Result<[bool; SLOT_COUNT as usize], Error> { - let status_ptr = unsafe { nitrokey_sys::NK_get_password_safe_slot_status() }; - if status_ptr.is_null() { - return Err(get_last_error()); - } - let status_array_ptr = status_ptr as *const [u8; SLOT_COUNT as usize]; - let status_array = unsafe { *status_array_ptr }; - let mut result = [false; SLOT_COUNT as usize]; - for i in 0..SLOT_COUNT { - result[i as usize] = status_array[i as usize] == 1; - } - unsafe { - libc::free(status_ptr as *mut libc::c_void); - } - Ok(result) - } - - /// Returns the name of the given slot (if it is programmed). - /// - /// This method also returns a `SlotNotProgrammed` error if the name is empty. - /// - /// # Errors - /// - /// - [`InvalidSlot`][] if the given slot is out of range - /// - [`SlotNotProgrammed`][] if the slot is not programmed - /// - /// # Example - /// - /// ```no_run - /// use nitrokey::GetPasswordSafe; - /// # use nitrokey::Error; - /// - /// # fn try_main() -> Result<(), Error> { - /// let mut manager = nitrokey::take()?; - /// let mut device = manager.connect()?; - /// match device.get_password_safe("123456") { - /// Ok(pws) => { - /// let name = pws.get_slot_name(0)?; - /// let login = pws.get_slot_login(0)?; - /// let password = pws.get_slot_login(0)?; - /// println!("Credentials for {}: login {}, password {}", name, login, password); - /// }, - /// Err(err) => eprintln!("Could not open the password safe: {}", err), - /// }; - /// # Ok(()) - /// # } - /// ``` - /// - /// [`InvalidSlot`]: enum.LibraryError.html#variant.InvalidSlot - /// [`SlotNotProgrammed`]: enum.CommandError.html#variant.SlotNotProgrammed - pub fn get_slot_name(&self, slot: u8) -> Result<String, Error> { - result_from_string(unsafe { nitrokey_sys::NK_get_password_safe_slot_name(slot) }) - .and_then(get_pws_result) - } - - /// Returns the login for the given slot (if it is programmed). - /// - /// This method also returns a `SlotNotProgrammed` error if the login is empty. - /// - /// # Errors - /// - /// - [`InvalidSlot`][] if the given slot is out of range - /// - [`SlotNotProgrammed`][] if the slot is not programmed - /// - /// # Example - /// - /// ```no_run - /// use nitrokey::GetPasswordSafe; - /// # use nitrokey::Error; - /// - /// # fn try_main() -> Result<(), Error> { - /// let mut manager = nitrokey::take()?; - /// let mut device = manager.connect()?; - /// let pws = device.get_password_safe("123456")?; - /// let name = pws.get_slot_name(0)?; - /// let login = pws.get_slot_login(0)?; - /// let password = pws.get_slot_login(0)?; - /// println!("Credentials for {}: login {}, password {}", name, login, password); - /// # Ok(()) - /// # } - /// ``` - /// - /// [`InvalidSlot`]: enum.LibraryError.html#variant.InvalidSlot - /// [`SlotNotProgrammed`]: enum.CommandError.html#variant.SlotNotProgrammed - pub fn get_slot_login(&self, slot: u8) -> Result<String, Error> { - result_from_string(unsafe { nitrokey_sys::NK_get_password_safe_slot_login(slot) }) - .and_then(get_pws_result) - } - - /// Returns the password for the given slot (if it is programmed). - /// - /// This method also returns a `SlotNotProgrammed` error if the password is empty. - /// - /// # Errors - /// - /// - [`InvalidSlot`][] if the given slot is out of range - /// - [`SlotNotProgrammed`][] if the slot is not programmed - /// - /// # Example - /// - /// ```no_run - /// use nitrokey::GetPasswordSafe; - /// # use nitrokey::Error; - /// - /// # fn try_main() -> Result<(), Error> { - /// let mut manager = nitrokey::take()?; - /// let mut device = manager.connect()?; - /// let pws = device.get_password_safe("123456")?; - /// let name = pws.get_slot_name(0)?; - /// let login = pws.get_slot_login(0)?; - /// let password = pws.get_slot_login(0)?; - /// println!("Credentials for {}: login {}, password {}", name, login, password); - /// # Ok(()) - /// # } - /// ``` - /// - /// [`InvalidSlot`]: enum.LibraryError.html#variant.InvalidSlot - /// [`SlotNotProgrammed`]: enum.CommandError.html#variant.SlotNotProgrammed - pub fn get_slot_password(&self, slot: u8) -> Result<String, Error> { - result_from_string(unsafe { nitrokey_sys::NK_get_password_safe_slot_password(slot) }) - .and_then(get_pws_result) - } - - /// Writes the given slot with the given name, login and password. - /// - /// # Errors - /// - /// - [`InvalidSlot`][] if the given slot is out of range - /// - [`InvalidString`][] if the provided token ID contains a null byte - /// - /// # Example - /// - /// ```no_run - /// use nitrokey::GetPasswordSafe; - /// # use nitrokey::Error; - /// - /// # fn try_main() -> Result<(), Error> { - /// let mut manager = nitrokey::take()?; - /// let mut device = manager.connect()?; - /// let pws = device.get_password_safe("123456")?; - /// let name = pws.get_slot_name(0)?; - /// let login = pws.get_slot_login(0)?; - /// let password = pws.get_slot_login(0)?; - /// println!("Credentials for {}: login {}, password {}", name, login, password); - /// # Ok(()) - /// # } - /// ``` - /// - /// [`InvalidSlot`]: enum.LibraryError.html#variant.InvalidSlot - /// [`InvalidString`]: enum.LibraryError.html#variant.InvalidString - pub fn write_slot( - &mut self, - slot: u8, - name: &str, - login: &str, - password: &str, - ) -> Result<(), Error> { - let name_string = get_cstring(name)?; - let login_string = get_cstring(login)?; - let password_string = get_cstring(password)?; - get_command_result(unsafe { - nitrokey_sys::NK_write_password_safe_slot( - slot, - name_string.as_ptr(), - login_string.as_ptr(), - password_string.as_ptr(), - ) - }) - } - - /// Erases the given slot. Erasing clears the stored name, login and password (if the slot was - /// programmed). - /// - /// # Errors - /// - /// - [`InvalidSlot`][] if the given slot is out of range - /// - /// # Example - /// - /// ```no_run - /// use nitrokey::GetPasswordSafe; - /// # use nitrokey::Error; - /// - /// # fn try_main() -> Result<(), Error> { - /// let mut manager = nitrokey::take()?; - /// let mut device = manager.connect()?; - /// let mut pws = device.get_password_safe("123456")?; - /// match pws.erase_slot(0) { - /// Ok(()) => println!("Erased slot 0."), - /// Err(err) => eprintln!("Could not erase slot 0: {}", err), - /// }; - /// # Ok(()) - /// # } - /// ``` - /// - /// [`InvalidSlot`]: enum.LibraryError.html#variant.InvalidSlot - pub fn erase_slot(&mut self, slot: u8) -> Result<(), Error> { - get_command_result(unsafe { nitrokey_sys::NK_erase_password_safe_slot(slot) }) - } -} - -impl<'a, 'b> Drop for PasswordSafe<'a, 'b> { - fn drop(&mut self) { - // TODO: disable the password safe -- NK_lock_device has side effects on the Nitrokey - // Storage, see https://github.com/Nitrokey/nitrokey-storage-firmware/issues/65 - } -} - -impl<'a> GetPasswordSafe<'a> for Pro<'a> { - fn get_password_safe(&mut self, user_pin: &str) -> Result<PasswordSafe<'_, 'a>, Error> { - get_password_safe(self, user_pin) - } -} - -impl<'a> GetPasswordSafe<'a> for Storage<'a> { - fn get_password_safe(&mut self, user_pin: &str) -> Result<PasswordSafe<'_, 'a>, Error> { - get_password_safe(self, user_pin) - } -} - -impl<'a> GetPasswordSafe<'a> for DeviceWrapper<'a> { - fn get_password_safe(&mut self, user_pin: &str) -> Result<PasswordSafe<'_, 'a>, Error> { - get_password_safe(self, user_pin) - } -} |