aboutsummaryrefslogtreecommitdiff
path: root/nitrocli/src/commands.rs
Commit message (Collapse)AuthorAge
* Move nitrocli source code into repository rootDaniel Mueller2020-04-04
| | | | | | Now that all vendored dependencies have been removed, this change moves the program's source code from the nitrocli/ directory into the root of the repository.
* Update minimum required Rust version to 1.35.0Daniel Mueller2019-12-31
| | | | | | | | | This change updates the minimum required version of Rust to 1.35.0. The motivation for doing so is at least two fold. First, next we want to bump the nitrokey crate to version 0.4.0 and it requires Rust 1.34.0 as a minimum. Second, and perhaps more importantly, though, in 1.34.0 a clippy lint regressed, breaking our pipeline. That is the reason why we are going to 1.35.0 instead.
* Update nitrokey crate to 0.4.0-alpha.3Daniel Mueller2019-08-12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | This change updates the version of the nitrokey crate that we use to 0.4.0-alpha.3. This version is the supposedly last pre-release before 0.4.0, with no further major anticipated changes. In order to integrate with this new version we have to adjust the way we connect to a Nitrokey device by funneling those connection requests through a global manager object. The rationale behind that step being that the underlying libnitrokey actually cannot handle access of multiple devices at the same time, and so the manager object is used to prevent accidental wrong concurrent usage. Because a device object now effectively keeps a reference to the manager, we need to provide an additional lifetime to that and derived objects. Lastly, the use of a manager is also the reason why the tests had to be adjusted to no longer accept device objects in their signatures, but only the respective model for which to invoke the test. That is required because, as elaborated earlier on, having a device object implies having taken a reference to a manager (in that case owned by nitrokey-test), and that reference clashes with the nitrocli code itself attempting to take the manager. We side step this problem by merely accepting a Model object, which can be passed around independently of the manager itself, meaning that nitrokey-test does not need to hold such a reference while the test is run. Import subrepo nitrokey/:nitrokey at f150d59410eefdec2ae69b2422906a3d1d88aa07 Import subrepo nitrokey-sys/:nitrokey-sys at 8695e2c762807e033a86c8d03974b686d20cdd72 Import subrepo lazy-static/:lazy-static at b4b2b16aaa79dd7548e288455a0dbe4065bf4e1a
* Update nitrokey crate to 0.4.0-alpha.2Daniel Mueller2019-08-12
| | | | | | | | | | This change updates the dependency to nitrokey to version 0.4.0-alpha.2. In addition to minor interface changes for the get_*_firmware_version and get_*_retry_count functions, several functions that change the device state now require a mutable handle to the nitrokey. Hence, this patch a number of function signatures to accept mutable device objects. Import subrepo nitrokey/:nitrokey at 34efcfadf1436102e42144f710edabaa2c4b55cd
* Use nitrokey::DEFAULT_{ADMIN,USER}_PIN constantsRobin Krahl2019-12-16
| | | | | | Since version 0.4.0, nitrokey provides the default admin and user PIN as constants. This patch removes the constants from nitrocli and uses nitrokey's constant instead.
* Update nitrokey crate to 0.4.0-alpha.0Daniel Mueller2019-07-17
| | | | | | | | | | | This is patch marks the first step in the process of updating the nitrokey dependency to version 0.4. In particular, it integrates with the first alpha version. The main change on the nitrocli side accompanying the version bump is that the nitrokey::CommandError got replaced by a more general nitrokey::Error which includes the former variant. Import subrepo nitrokey/:nitrokey at d433189caefe6bd6c88da7fbb1d6e9304353eb83
* Properly pad user supplied hexadecimal strings to otp set subcommandDaniel Mueller2019-10-13
| | | | | | | | | | The library ultimately taking care of communicating with the Nitrokey device, libnitrokey, unconditionally expects hexadecimal strings supplied as part of the configuration of an OTP slot to have an even number of bytes. Users should not be aware of this detail and so with this change we take care of padding the supplied string with a leading zero to make such a configuration go through without an error.
* Correctly pad bytes with zero in hex conversionDaniel Mueller2019-10-13
| | | | | | | | | | | | When reading a secret in ascii or base32 format from the user, we perform a conversion of the potentially decoded string into hexadecimal bytes, because that is what libnitrokey expects. The format string we used in the conversion, however, did not account for padding with a leading zero for single digit results. E.g., the newline/line feed symbol '\n', which has a decimal value of 10 would result in the string 'a' being produced, whereas '0a' would be the correct result. This change corrects the format string to fix this problem.
* Introduce with_password_safe functionDaniel Mueller2019-07-14
| | | | | | | | | | Similar to the with_*device functions introduced in a previous change, this change introduces a with_password_safe function that is a short hand for opening the Nitrokey, retrieving a handle to the password safe, and invoking a user-supplied function on it. This function will allow us to prevent life time inference problems caused by passing around a PasswordSafe object, which will contain an additional reference (and with that, lifetime) in nitrokey version 0.4.
* Supply ExecCtx to op used in with_* and try_with_* functionsDaniel Mueller2019-07-14
| | | | | | | With an upcoming change we will require an ExecCtx in one of the op functions passed to the with_* and try_with_* functionality. To allow for such cases, this change adjusts the signature of those functions to provide a reference to such a context.
* Introduce TryInto<T> traitRobin Krahl2019-08-13
| | | | | | | | | | | This change introduces a new trait, TryInto, to the crate. In the future this trait will allow us to keep a flexible set of error result types from the various try_with_* functions, which use a certain nitrokey error variant to check for the entry of a wrong secret. Note that while a TryInto trait exists in Rust's standard library, that was not found to be helpful because we have no way to define it for nitrkey crate's error type. Because of that, we will always have a mismatch between our internal error and std::convert::Infallible.
* Introduce with_*device functionalityDaniel Mueller2019-07-14
| | | | | | | | | | | | | | | | | | The upcoming nitrokey 0.4 release changes the way a device handle can be acquired, requiring a manager instance for doing so in an attempt to prevent users from opening multiple sessions (which is not something that libnitrokey supports). A straight integration of the reworked API surface into our program would severely complicate the architecture because of the additional requirement of keeping a manager object around while a device is being used. To make the program more amenable to those changes in nitrokey, this patch reworks the way we interact with a device handle: instead of passing the device object around we pass in the functionality making use of it in the form of a function. In more concrete terms, instead of retrieving a device handle via get_device() we now have a with_device() function that takes care of opening the device and then passing it to a user-provided function.
* Use FnMut over Fn in try_with_* and authenticate functionsDaniel Mueller2019-07-14
| | | | | | | | | The try_with_* and authenticate functions accept a user-supplied function to work with. Currently this function is declared as Fn. That, however, is unnecessarily restrictive. With this change we declare said function an FnMut instead, which allows it to potentially capture variables from its environment in a mutable manner.
* Include Nitrokey model in error message when no device is foundDaniel Mueller2019-07-14
| | | | | | | | For functionality that explicitly works with the storage device we emit an error message stating that a "Nitrokey Storage" device could not be found. When the user chooses the model using the -m/--model argument that is not the case. With this patch we adjust the error message printed.
* Use map_err over or_else to convert errorsDaniel Mueller2019-07-14
| | | | | This patch replaces two cases where we use Result::or_else over the more idiomatic (and shorter) Result::map_err for converting errors.
* Add support for changing read-write mode of unencrypted volumeDaniel Mueller2019-06-08
| | | | | | | This change adds support for changing the read-write mode of the unencrypted volume. To do so, we introduce a new top-level command, unencrypted, with a new subcommand, set, that accepts the new mode of the volume.
* Reword an incorrect error messageDaniel Mueller2019-06-08
| | | | | | | | | This change rewords the error message that is emitted if the lock command fails. The old message was incorrectly stating a problem with the retrieval of the device's status. While at it, also slightly rephrase the description for the hidden command to be more in line with that of the other storage commands, and replace lowercase 'nitrokey' with a capitalized one in a few comments.
* Rename storage command to encryptedDaniel Mueller2019-05-27
| | | | | | | | This change is the last step in the process of restructuring the storage command. In particular, now that functionality pertaining hidden volumes has been moved out into a dedicated top-level command, it renames said command to encrypted, because dealing with the encrypted volume is the only functionality it provides.
* Make storage hidden subcommand a top-level commandDaniel Mueller2019-05-27
| | | | | | This patch marks the next step in the process of restructuring the storage command. Specifically, it promotes the storage hidden subcommand to a top-level command, hidden.
* Move storage status subcommand into status commandDaniel Mueller2019-05-27
| | | | | | | | In an attempt to rework the structure of the storage command to better accommodate future requirements for allowing to change the read-write state of the unencrypted volume (as well as potentially the encrypted one), this change removes the storage status subcommand and merges its output into the storage command.
* Clear cached PIN entry as part of pin set commandDaniel Mueller2019-06-01
| | | | | | | | | | When a PIN is changed using the pin set command, the last action is to confirm the operation with the previously used PIN. This step will cause this PIN, which is now stale and no longer valid, to be cached, which in turn can cause follow up command using the same PIN type to use this wrong cached entry for authentication. To fix this problem, this change explicitly clear the PIN entry from the cache after the PIN has been changed.
* Allow for disabling of secret cachingDaniel Mueller2019-05-27
| | | | | | | | | | | | So far we have cached secrets in gpg-agent(1) whenever that made sense to do (i.e., for the two PINs in most contexts but not for passwords). While there is reason to believe that such caching is desired by the majority of users, not everybody has a use for it. To give users an opportunity to opt out of such caching, this change introduces a new environment variable, NITROCLI_NO_CACHE, that, when present in the environment, instructs the program to bypass the cache for all operations that require a secret and to instead inquire such secrets each time they are needed.
* Check slot status before accessing the PWSRobin Krahl2019-01-26
| | | | | | | | | | | | The Nitrokey devices do not check whether a PWS slot is programmed before accessing it (upstream issues [0] [1]). Until this is fixed in the firmware, we have to manually check the slot status in pws get. This could have been done in libnitrokey or the nitrokey crate, yet this would lead to unnecessary commands if we check multiple fields of a slot at the same time. [0] https://github.com/Nitrokey/nitrokey-pro-firmware/issues/56 [1] https://github.com/Nitrokey/nitrokey-storage-firmware/issues/81
* Add the reset command to perform a factory resetRobin Krahl2019-01-26
| | | | | | After performing the factory reset, we also build the AES key so that the device is fully usable. Due to timing issue, we have to add a delay between the factory reset and building the AES key.
* Add test for storage hidden subcommandDaniel Mueller2019-01-20
| | | | | | | This change adds a test for the creation, opening, and closing of a hidden subvolume. In order to support that in a non-interactive fashion, we introduce and honor the NITROCLI_PASSWORD environment variable, that prevents an interactive password query.
* Implement storage hidden subcommandDaniel Mueller2019-01-20
| | | | | | | | | With this change we implement the storage hidden subcommand. We support creation, opening, and closing of hidden volumes. Note that the opening of a hidden volume automatically closes any opened encrypted volumes and vice versa. To that end, we force file system level caches to disk even from the storage open and storage hidden open commands.
* Drop '_pin' suffix from various pinentry functionsDaniel Mueller2019-01-19
| | | | | | Various functions in the pinentry module contain an arguably redundant '_pin' suffix in their name. Examples include inquire_pin and clear_pin. This change removes this part from their names.
* Move PIN choosing functionality into pinentry moduleDaniel Mueller2019-01-19
| | | | | | | | | The functionality we have in place for choosing a PIN can arguably be moved into the pinentry module: it can be considered logic directly related to working with PINs or secrets and that has no dependencies to unrelated modules of the program. This patch moves the choose_pin and check_pin functions into the pinentry module.
* Isolate cached PINs for multiple devices from each otherDaniel Mueller2019-01-11
| | | | | | | | | | | | | | | | | | | The application supports multiple devices both plugged in at the same time as well as when used after the other. However, the GPG cache ID we use for storing and retrieving the respective PIN is effectively a constant. This constraint can cause problems when devices have different PINs, as the PIN of a previously plugged in device may be reused for an operation on a different one. To resolve this problem this change adds the respective device's model and serial number to the cache ID. As each serial number is supposed to be different, this will ensure that the correct PIN is used for each device. With this change we also show the model and serial number of the currently used device in the pinentry dialog. Note that because we do not store the serial numbers of all previously plugged in devices, the pin clear command will only clear the PIN for the currently plugged in device. If a user wants to make sure that a cached PIN is cleared, the pin clear command should be invoked before unplugging the device.
* Implement From<&str> for ErrorRobin Krahl2019-01-26
| | | | | | This patch implements From<&str> for Error so that we can use Error::from(s) as a shorthand for Error::Error(s.to_string()). It also replaces Error::Error with Error::from where possible.
* Refactor get_device to use nitrokey::connect_modelRobin Krahl2019-01-26
| | | | | | | | | nitrokey 0.3.1 introduced the connect_model function that connects to a specific model given by an enum variant and returns a DeviceWrapper. This new function allows us to remove the manual selection of a connection method from the get_device function. We only have to implement From<DeviceModel> for nitrokey::Model to be able to convert our model enum to nitrokey's model enum.
* Report command errors properlyDaniel Mueller2019-01-09
| | | | | | | | | | | | So far we have taken all nitrokey::CommandError objects and put them in formatted form into the Error::Error variant. What we really should do, though, is to preserve the original error, with the additional context provided by the caller, and report that up the stack directly. Doing so has at least the benefit that we are able to check for expected errors without hard coding the textual representation as maintained by the nitrokey create. This change refactors the code accordingly and adds two tests for such expected error codes.
* Honor context provided Admin & User PIN in pin commandsDaniel Mueller2019-01-09
| | | | | | | | | | | The second source of interactivity comes from the pin set and pin unblock commands, which also inquire with the pinentry module to ask the user for a PIN. This change adjusts the two commands to honor the PINs as available in the command execution context. It also updates the documentation to reflect the availability of the newly introduced and honored environment variables NITROCLI_ADMIN_PIN & NITROCLI_USER_PIN as well as NITROCLI_NEW_ADMIN_PIN & NITROCLI_NEW_USER_PIN.
* Make try_with_pin_and_data logic honor execution context PINsDaniel Mueller2019-01-09
| | | | | | | | | | The try_with_pin_and_data function is used by many commands to ask the user for a PIN in an interactive manner. Because we do not want to have any interactivity in our tests, we should honor the command execution's admin & user PIN fields from this function, if set. This change adjusts the function to honor the command execution context's admin & user PIN, if set. In order to do so it also adjusts the callers to hand through the context to begin with.
* Simplify try_with_pin_and_data functionDaniel Mueller2019-01-09
| | | | | | | | | | The try_with_pin_and_data function is a fairly complex beast. Part of that complexity stems from the returned Result value, whose error part not only contains the error but also the previously passed in data. As it turns out, though, this data as returned is never actually consumed by any client. Hence, this change simplifies the logic slightly by removing all the additional complexity that this tuple return entailed.
* Make pinentry::inquire_pin return String directlyDaniel Mueller2019-01-09
| | | | | | | | | | | | | | | The inquire_pin function of the pinentry module used to return a vector of bytes, as that is what is ultimately read from the gpg-agent process. All clients of this function, however, work with a string and, hence, convert this vector into a string. As it turns out, for better or worse, the pinentry::parse_pinentry_pin function (which produces the result of inquire_pin) internally already works with a string but then converts it back. That is both not useful and a waste of resources. This change adjusts both functions of interest to simply return a String object instead, removing the need for conversions at the clients. While at it, the patch also removes the need for a bunch of unnecessary allocations caused by sub-par parameter type choice.
* Use 'pin' instead of 'passphrase'Daniel Mueller2019-01-09
| | | | | | | | | | | | In the past we have used the term 'passphrase' to refer to the data retrieved through the pinentry module and that terminology has permeated the commands module as well. However, on the Nitrokey side we talk about PINs most of the time (despite a lack of an requirement for being actual numbers). In an attempt to unify terminology a bit more, this change renames all occurrences of the term 'passphrase' with PIN. This renaming has the nice side effect of making the code more concise because the latter is much shorter than the former.
* Show fmt::Display formatted errors instead of fmt::Debug onesDaniel Mueller2019-01-08
| | | | | | | | | At some point in the past nitrokey::CommandError was lacking an implementation of the fmt::Display trait. Hence, we fell back to printing these errors in debug format. Since version 0.2.0 of the crate fmt::Display is implemented for these errors. With this change we use it to report more user-friendly error messages.
* Emit all output to custom stdio channelsDaniel Mueller2019-01-05
| | | | | | | | | | | This change continues and concludes the effort of using customizable stdio channels for output of data from the program. It does so by replacing the standard println macro with a custom one that outputs the data to the supplied context's stdout object. Because this object is injected from the main function, it will be possible for tests invoking this function to supply custom Write objects that can buffer this data and make it available for verification purposes.
* Work with mutable ExecCtx referencesDaniel Mueller2019-01-05
| | | | | | | | | | So far we have used a read-only reference to a command execution context and passed that through to all consumers. However, with upcoming changes we would will need to provide data that can be modified. This change adjusts all function signatures accordingly. Also, because the ExecCtx will contain references itself in the future, this change already introduces a lifetime for the struct, as that also requires signature adjustments.
* Add the base32 format for OTP secretsRobin Krahl2019-01-13
| | | | | | | Many applications display OTP secrets in the base32 format (according to RFC 4648). This patch adds base32 as a possible value for the --format option to the otp set subcommand.
* Refactor prepare_secret functionRobin Krahl2019-01-13
| | | | | | | This patch refactors the prepare_secret function by renaming it to prepare_ascii_secret and by moving the formatting of a bytes slice as a hex string into the format_bytes function. This prepares for adding a the base32 format in a future patch.
* Add the --format option to otp set to select the secret formatRobin Krahl2019-01-13
| | | | | | | | | | | | | | This patch introduces the -f/--format options for the otp set subcommand to specify the format of the OTP secret. Previously, the default format was hexadecimal and ASCII format could be selected using the --ascii option. The new --format option takes the argument hex or ascii, defaulting to hex, and replaces the --ascii option. This patch does not remove the --ascii option but marks it as deprecated. It may not be set together with --format, and a warning is printed if it is set. It should be deleted with the next minor release. This patch prepares the addition of a new format, base32.
* Update nitrokey crate to 0.3.0Daniel Mueller2019-01-05
| | | | | | This change updates the nitrokey crate to version 0.3.0. Import subrepo nitrokey/:nitrokey at 3593df8844b80741e2d33c8e5af80e65760dc058
* Add the --model option to restrict the device model to connect toRobin Krahl2019-01-13
| | | | | | | | | | | | This patch adds the -m/--model option that can be used to restrict the device model to connect to. Per default, nitrocli connects to any available Nitrokey device. If this new option is set, it will instead only connect to devices of the given Nitrokey model. We introduce a new struct DeviceModel instead of using nitrokey::DeviceModel to make sure that the command-line options are parsed properly. On the long term, we should add a connect_model function to the nitrokey crate to make the connection code easier.
* Introduce -v/--verbose optionDaniel Mueller2019-01-04
| | | | | | | | | | | | | | | | This change introduces a new option, -v/--verbose, that can be used to increase the log level of libnitrokey. The option can be supplied multiple times, with each occurrence increasing the verbosity of the logging. On the implementation side, the option is set as part of connecting the device (piggy-backing on the previously introduced command execution context), although it describes global state that strictly speaking could be set anywhere. It is bad enough that libnitrokey just prints log messages to stderr (and does not accept a file handle) and that it does not track the log level on a per-device basis, but we don't want setting of global state from arbitrary locations inside the program. Instead, let's do that along with what pretty much is the first call into libnitrokey anyway: the connection to the device.
* Introduce command execution context supportDaniel Mueller2019-01-04
| | | | | | | | | In the future we will need the ability to pass additional state that is deduced from arguments or elsewhere into the commands module. To enable such scenarios, this change introduces the concept of a command execution context. Such a context can store more or less arbitrary data, and the args module will take care of passing it through to the individual commands.
* Use libc provided sync functionDaniel Mueller2019-01-04
| | | | | | | | | | | | In order to flush file system level buffers to disk we use the sync function. The way we made this function known to the crate was by explicitly declaring it as extern "C" and linking against libc. However, given that we already (indirectly) depend on libc through the nitrokey crate (and that is unlikely to change) we may as well make libc a direct dependency and invoke the function through the crate. Given that the libc crate is available for a variety of platforms, it seems likely that its approach to interfacing with the system libc library is more portable than our hand rolled version.
* Adjust get_error function to accept CommandError by valueDaniel Mueller2019-01-03
| | | | | | | | With the recent update of the nitrokey create the nitrokey::CommandError enum has become trivially copyable. Hence, there is no more point in passing a reference to it to the get_error function. To that end, this change adjusts the signature to accept an owned value instead.
* Implement the lock commandRobin Krahl2019-01-07
| | | | | | This patch implements the lock command that locks the password safe and, on the Nitrokey Storage, the encrypted volume. See issue #18 for details on the locking mechanism.