aboutsummaryrefslogtreecommitdiff
path: root/nitrocli/src/main.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.
* Remove unions_with_drop_fields lintDaniel Mueller2019-12-30
| | | | | With Rust 1.40 the unions_with_drop_fields lint has been removed. This change removes it from our list of lints as well.
* Introduce NITROCLI constantDaniel Mueller2019-08-24
| | | | | | This change introduces a constant for the frequently used string "nitrocli" to the program and replaces usages of those strings with references to the constant.
* Downgrade crate-level lints to 'warn'Daniel Mueller2019-07-13
| | | | | | | | | | | | | We recently fixed a compilation failure in some test code caused by a use declaration that was ultimately unused. To this point we were under the impression that there was a set of lints that were known to be potentially changing in backwards incompatible ways while others would not. Discovery of unused use declarations or symbols was always assumed to fall into the latter category. Because such a build breakage due to semantic change in what a lint can detect by now is a repeated pattern (with dire consequences), this change downgrades all 'deny'-style lints to warnings in order to prevent similar problems in the future.
* Remove explicit change of global allocatorDaniel Mueller2019-06-17
| | | | | | | | | | This change removes the explicit change of the global allocator to the system allocator that we introduced a while back. The reason this was needed in the past was due to Rust's use of jemalloc in the default configuration, which increases binary size quite significantly. However, with Rust issue #36963 fixed, jemalloc is now an explicit opt-in and the system allocator is the default choice -- rendering our explicit change rather pointless.
* 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.
* Remove no longer used duplicate_associated_type_bindings lintDaniel Mueller2019-01-26
| | | | | | | The duplicate_associated_type_bindings lint seems to have been removed with the Rust 1.32 release. This change removes the lint from the program to prevent the newly introduced warning from being emitted.
* 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.
* Properly flush stdout before process exitDaniel Mueller2019-01-12
| | | | | | | | | | | We exit the program using the process::exit function. This function just exits the program directly, without any cleanup. That can be a problem because IO buffers may not be flushed either. For a (typically) line buffered entity like stdout that may result in data not terminated by a newline symbol being not displayed properly. This change explicitly flushes stdout before exiting the process to alleviate this problem. Note that stderr output is unaffected, because stderr is not buffered by design.
* Switch to using the system allocatorDaniel Mueller2019-01-07
| | | | | | | | | | | | | | | | | | In the past we have already taken a couple of steps to reduce the size of the final binary, arguing that binary size is the metric of most relevance for the program at hand: - the memory footprint is close to irrelevant because the program does not stay resident in memory for long - execution speed is likely dominated by communication with the Nitrokey itself, which is a slow I/O device With that in mind, this change decreases the binary size further by swapping the default allocator we use (typically jemalloc) with the system allocator (which is malloc based on Unix systems). Given that we are by no means allocation sensitive, there is no point in wasting binary size on something that adds no value. This change decreases the binary size by another 324 KiB (for an already stripped release mode binary).
* Introduce Admin and User PIN fields to execution contextDaniel Mueller2019-01-09
| | | | | | | | | | | | | | In order to run tests fully non-interactively we need to avoid the need for using the GPG agent's PIN entry and caching mechanism. To accomplish that, we first need an alternate way to supply the PINs to use to the program. This change offers such a way by extending the execution context with two fields representing the PINs that are populated by corresponding environment variables, NITROCLI_ADMIN_PIN & NITROCLI_USER_PIN, if set. While only two PINs are required right now, because the program allows for the changing of each of the PINs, we also add two fields representing new PINs. These latter two fields are populated by the NITROCLI_NEW_ADMIN_PIN and NITROCLI_NEW_USER_PIN environment variables.
* Auto generate argument enumsDaniel Mueller2019-01-06
| | | | | | | | | | | | The argparse module we use for parsing events expects an enum in order to convey what subcommand has been supplied as an argument. Such an enum also needs to implement str::FromStr and, preferably, fmt::Display. Manually writing down those definitions is error-prone, tedious, and adds no value -- only lines of code. As it turns out the proper definitions can be generated with relative easy with a declarative macro, making the code much more concise. Hence, with this change we use a newly introduced macro for generating those enums.
* Add first set of integration testsDaniel Mueller2019-01-05
| | | | | | | | | This change introduces the first set of integration-style test for the application. Those tests may or may not connect to an actual Nitrokey device (depending on what they test). We use the nitrokey-test crate's test attribute macro to automatically dispatch tests to connected devices or skip them if a required device is not present. It also provides the means for automatically serializing tests.
* 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.
* Supply customizable stdio channels to argparseDaniel Mueller2019-01-05
| | | | | | | | | | | | | | | | | | | | | | | | | In order to properly test the program we need to have a way to intercept data printed to the stdio channels. There are different ways to accomplish that task. While it is reasonably easy to just start the program as a dedicated process doing so properly may be problematic from inside a test because either the path to the binary has to be retrieved or cargo -- the entity which knows the path -- be invoked. None of these approaches is very appealing from a testing and code complexity point of view: an additional fork means additional sources of errors and flakiness, executing cargo has the potential to even cause rebuilds of parts of the program, and while we are already testing against a slow I/O device this additional code running is unlikely to go unnoticed in the long-term. Lastly, doing so also means that we leave Rust's type safety behind when dealing with errors that could be nicely match'ed on when the test invocation is just a function call. To avoid all this complexity we instead strive for basically just running the main function. This patch marks a first step towards achieving this goal. It introduces the infrastructure to supply custom Write objects to the argument parsing functionality. Once more we piggy-back on the command execution context and add objects representing stdout and stderr to it. We further ensure that this context is passed to the argument parser invocations.
* Make 'open' and 'close' subcommands of new 'storage' commandDaniel Mueller2018-12-27
| | | | | | | | | | | | | Upon their inception, the 'open' and 'close' commands were pretty much the only relevant commands the program provided and it made sense to have them reside in the root namespace. By now we support more commands and have started to structure them in a more hierarchical fashion. To go with the flow, this change introduces a new 'storage' command and makes the existing 'open' and 'close' commands subcommands of it. We chose the name 'storage' (over, say, 'volume') because we plan to move the printing of the storage related status from the 'status' root level command into a subcommand within 'storage'.
* Port argument handling to argparseRobin Krahl2018-12-23
| | | | | | | | | This patch replaces the macro for argument parsing with `argparse::ArgumentParser` from the argparse crate. It moves the application logic to the `commands` module and the argument parsing to the `options` module. An enum is used to represent the available commands. The code is based on the `subcommands.rs` example shipped with argparse.
* Factor out new commands.rs fileDaniel Mueller2018-12-20
| | | | | | | In order to prepare for the new argument parsing support based on the argparse crate, this change factors out the existing code used for responding to commands in a new file, commands.rs. No semantic change is introduced.
* Make code conforming to rustfmt's expectationsDaniel Mueller2018-12-17
| | | | | | | | | | | | | | An automated code formatter can help tremendously in reducing the amount of cognitive energy wasted on thinking about the "best" formatting of code as well as the number of nitpicks reviews typically get -- the format is machine checked (and enforced) and there is usually little to no discussion about the validity. To reach the goal of having such automated enforcement, we want to run the rustfmt tool as part of the CI pipeline. With rustfmt having reached 1.0 recently, the believe is that by now the formatting is reasonably stable and usable for this purpose. In that light, this change formats the code using rustfmt and prepares for such an automated style check.
* Rename libnitrokey to nitrokeyRobin Krahl2018-12-17
| | | | | | | Currently, the nitrokey crate is renamed to libnitrokey in Cargo.toml as there used to exist a nitrokey module in this crate. As this module does no longer exist and is not likely to return, this patch removes the customized name for the nitrokey crate.
* Port the status command to libnitrokeyRobin Krahl2018-12-17
| | | | | | This patch removes the raw hidapi implementation of the status command and all utility methods that are no longer needed. With this patch, all device communication is performed using libnitrokey.
* Port the open and close commands to libnitrokeyRobin Krahl2018-12-17
| | | | | | | | | | | | | | This patch removes the raw hidapi implementations of the Enable Encrypted Volume and Disable Encrypted Volume commands and replaces them with the methods enable_encrypted_volume and disable_encrypted_volume of the Storage struct provided by the nitrokey trait. To provide some context to the error messages, the errors are wrapped using the map_err method of the Result enum and the get_error function that combines a nitrokey error code and a string into a nitrocli error. It would be more idiomatic to define a conversion from a nitrokey error to a nitrocli error, but then we would lose information about the context of the error.
* Enable more lintsDaniel Mueller2018-12-11
| | | | | | | | Given that development is picking up speed again we should accept all the help we get from the compiler to catch issues as early as possible. To that end, this change enables more lints for the program. As "usual", lints that are suspected to potentially change in future versions of Rust are reported as warnings and not errors.
* Compile program with 2018 Edition of RustDaniel Mueller2018-12-11
| | | | | | | With the 1.31 release of Rust support for Edition 2018 has reached the stable tool chain. This change enables compilation based off of this new edition for the crate. This change resolves issue #6.
* Enable rust_2018_idioms lintDaniel Mueller2018-12-10
| | | | | | | | This change enables the rust_2018_idioms lint which helps enforce the usage of Rust 2018 code idioms. A while back the "impl trait" feature stabilized and along with it trait objects are supposed to be prefixed with "dyn". This change adjusts the code accordingly.
* Enable rust_2018_compatibility lintDaniel Mueller2018-12-10
| | | | | | | | In preparation for the switch to using Rust 2018, this change enables the rust_2018_compatibility lint. Along with that enablement we fix the warnings emitted by it, which evolve around the module system changes Rust has gone through and that require us to prefix initial uses of crate local modules with "crate".
* Add support for multiple PIN typesRobin Krahl2018-12-11
| | | | | | | | Currently, the pinentry module only supports querying the user PIN. The Nitrokey devices also have an admin PIN. This patch adds support for querying multiple PIN types to the pinentry module. While this is currently not used, it will be needed to add support for administrative commands like unlocking the device or changeing the user PIN.
* Show error in pinentry dialog instead of printing to stdoutRobin Krahl2018-12-11
| | | | | | | | | Currently, the error message for a wrong password is printed to the standard output. Yet the standard output might not be visible to the user if they are using the curses frontend for pinentry. Pinentry already supports displaying an error message in the passphrase prompt. This patch moves the error message from the standard output to the pinentry prompt.
* Fix issues reported by clippyDaniel Mueller2018-02-18
| | | | | The clippy tool has a couple of suggestions on how to improve the code. This change applies them to the project's code base.
* Flush filesystem caches before closing encrypted volumeDaniel Mueller2017-04-09
| | | | | | | | When closing the encrypted volume we could potentially cause the volume to be in an inconsistent state if writes to it were cached by the operating system. To mitigate this case this patch causes an invocation to the sync(2) system call to flush outstanding writes to disk.
* Wait until encrypted volume is opened/closedDaniel Mueller2017-04-09
| | | | | | | | | Until now we treated any response but "ok" and "idle" to the encrypted volume opening command as an error and reported it. However, the opening process is a potentially long running and it is very likely that the nitrokey reports a couple of "busy" messages. This change implements the logic to wait until the nitrokey either reports an error or a successful open.
* Add 'clear' commandDaniel Mueller2017-04-09
| | | | | | | | | | We currently unconditionally use gpg-agent to enter the PIN to use when opening the encrypted volume. The agent has the advantage of caching the password for us so that subsequent invocations against the same cache entry can be served without user interaction. For various reasons, however, it can be desirable to have the ability to remove this entry from the cache. This change introduces a new command 'clear' that achieves precisely this task.
* Detect wrong password during 'open' commandDaniel Mueller2017-04-09
| | | | | | | | | | When a wrong password is entered when attempting to open the encrypted volume the nitrokey will report that in the form of an error. In such a case we should retry the operation after asking the user for the corrected password. This change implements this logic. Note that because we use gpg-agent for the PIN inquiry and because it caches passwords by default we must make sure to clear the cache before retrying.
* Add 'status' commandDaniel Mueller2017-04-09
| | | | | | | | | | | The nitrokey supports a status command that instructs it to report details about itself. This data includes general useful information such as the current version of the firmware being installed along with more contextual bits such as the number of remaining retries for the user and admin PINs or whether the different volumes (unencrypted, encrypted, hidden) are writable. This change introduces the 'status' command line option that can be used to retrieve this information from the nitrokey and to display it.
* Introduce transmit function subsuming send and receiveDaniel Mueller2017-04-08
| | | | | | | | | The send a report, wait for some time, and receive a response pattern is used in many places already and more are to come. In fact, no send should ever happen without the wait for a response. To that end, this change introduces a new 'transmit' function that performs the exactly this task: send a report and return the response to it.
* Retry send/receive on failureDaniel Mueller2017-04-08
| | | | | | | | | | It is possible that sending or receiving a feature report fails. Such failures can have multiple reasons, including transient problems. In the case of such a transient failure we should retry the operation. This change accomplishes this feat by retrying a send in case of a failure up to a maximum of three times, with a small wait in between. It also introduces the logic or receiving a response (which is not yet evaluated fully).
* Receive command responsesDaniel Mueller2017-03-30
| | | | | | | | | By just sending a command to the nitrokey alone we have no idea of what actually happened on the side of the nitrokey. A command could simply be invalid in the current context or the stick could be busy or in a failure state. In order to determine the success of an operation, this change adds the logic to retrieve the response from the nitrokey as well.
* Send HID feature report to open/close the encrypted volumeDaniel Mueller2017-03-28
| | | | | | | With this change we assemble a HID feature report and send it to the nitrokey device. Feature reports are the objects used for sending commands to the nitrokey. We create two different reports for opening and closing of the encrypted volume.
* Discover and open nictrokey using libhidapiDaniel Mueller2017-03-26
| | | | | | | | | | | This change uses the 'hid' crate to discover and open the Nitrokey Storage device. 'hid' is a wrapper around libhidapi (its libusb back-end in particular). Being a command line application some sort of parameter handling needs to happen. The approach we take is very simple for now to minimize the number of dependencies: we just compare the first argument against the expected ones and raise an error if no match was found. Because we only have positional arguments right now this is all we need.
* Add basic scaffoldingDaniel Mueller2017-03-03
This change adds the basic scaffolding for the nitrocli application. The scaffolding was created using the following command: $ cargo new --bin nitrocli The application aims at providing a command line interface for the Nitrokey Storage device.