| Commit message (Collapse) | Author | Age |
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
The help text for the otp set -a/--algorithm option is lacking the
closing parenthesis in the help text. This change adds it.
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
| |
This change updates the nitrokey crate to version 0.3.0.
Import subrepo nitrokey/:nitrokey at 3593df8844b80741e2d33c8e5af80e65760dc058
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
| |
We have a Result::unwrap in the error path of handling io::Error
objects. I have actually seen that fail, masking the original error. We
should not unwrap there and in fact we don't have to, as io::Error
implements fmt::Display just fine.
This may have changed in the past, as the construct we had is much more
convoluted than necessary and would only have been written if a direct
formatting was not possible.
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
| |
This patch adds documentation and examples for the lock command to the
README and to the man page. It also adds the lock command to the
top-level help message.
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
This patch implements the pws status command that can be used to print
status information for the slots in the password safe.
|
|
|
|
|
| |
This patch implements the pws clear command which allows the user to
clear a slot in the password safe.
|
|
|
|
| |
This patch adds the pws set subcommand that writes a PWS slot.
|
|
|
|
|
|
|
|
|
| |
This patch implements the pws get subcommand that provides read access
to a slot of the password safe. Per default, all available information
– slot name, login and password – are printed. If one or more of the
options --name, --login and --password are set, only the selected fields
are printed. If --quiet is set, the field description is omitted such
that the output can be easily parsed by other applications.
|
|
|
|
|
| |
This patch adds the basic structure for the pws command that can be used
to access the password safe on the Nitrokey Pro and Nitrokey Storage.
|
|
|
|
|
| |
This change implements the pin set command which can be used to change
a Nitrokey's user or admin PIN.
|
|
|
|
|
|
|
| |
This patch implements the pin unblock command that unblocks and resets
the user PIN. The name unblock is chosen over libnitrokey's unlock to
be consistent with the GnuPG terminology and to avoid confusion with the
unrelated lock command.
|
|
|
|
|
|
|
|
|
| |
We have functionality for changing the Nitrokey's user & admin PINs as
well as for resetting the user PIN coming up. With the prospect of this
new functionality arriving, it makes sense to introduce a new top-level
command for the sole purpose of PIN management.
This change introduces such a command, pin, and moves the existing clear
command for clearing the PIN cache into it.
|
|
|
|
|
|
|
| |
The mode argument is used to specify the context of the pinentry dialog:
querying an existing passphrase or prompting the user to choose a new
PIN. It is used to choose a description and to decide whether to show a
quality bar that measures the password strength.
|
|
|
|
|
|
|
|
|
|
| |
This patch changes the otp get command to set the Nitrokey's time before
generating a one-time password using the TOTP algorithm. Per default,
it sets the time to the current system time. If the --time option is
set, it uses its value instead. See issue #34 [0] for a discussion of
this change.
[0] https://github.com/d-e-s-o/nitrocli/issues/34
|
|
|
|
|
|
|
|
|
|
| |
The 'status' command has traditionally printed information about the
connected Nitrokey and that included storage specific data if the device
present is a Nitrokey Storage.
Given that we have a root-level 'storage' command it arguably makes
sense to move the printing of the storage related status information
into a 'status' sub-command of the said command, which makes the output
more predictable.
|
|
|
|
|
|
|
|
| |
We have kept the code organized such that the function for handling a
command is located above the functions taking care of handling the
subcommands.
This change moves the storage_* subcommand functions below the storage
function to be more consistent with existing code.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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'.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This change implements the config set subcommand. The subcommand changes
the configuration of a Nitrokey device.
Its structure is more complex as it allows partial modifications: The
user does not have to change all settings, but may choose to change only
some. At the same time, the binding settings can be either set to a
value or disabled. Therefore, we have the --{num,caps,scrol}lock
options to set a value and the --no-{num,caps,scrol}lock options to
disable the value. If none of the two is set, the setting is not
changed.
|
|
|
|
|
| |
This change implements the config get subcommand. The subcommand reads
the device configuration and prints it.
|
|
|
|
|
| |
This patch adds the top-level config command. Its subcommands will
provide access to the device configuration.
|
|
|
|
|
|
|
|
| |
Currently, the status command fails for a Nitrokey Pro. This patch
changes the command to also print basic status information for Pro
devices. For the sake of consistency, the common status is always
queried using the common `Device` functions, even if the Storage status
includes the same information.
|
|
|
|
|
|
| |
This patch extracts the print_status function that prints the status
fields common to all supported Nitrokey devices from the
print_storage_status function.
|
|
|
|
|
| |
The print_status function only prints the Storage-specific status
struct. Therefore it is renamed to print_storage_status.
|
|
|
|
|
|
|
|
| |
This patch introduces the `otp status` subcommand that lists all OTP
slots and their current status. To avoid hardcoding the number of slots
per type, we iterate all slots until we get an `InvalidSlot` error
(assuming that the set of valid slots is {0, ..., n} for some n). The
`status` command is quite slow as we have to query each slot separately.
|
|
|
|
| |
This patch implements the `otp clear` subcommand that erases an OTP slot.
|
|
|
|
|
|
|
|
|
|
| |
This patch implements the `otp set` subcommand that configures an OTP
slot. There are two ways to specify an OTP secret: as a hexadecimal
string (that means that every two characters are interpreted as a
hexadecimal representation of one byte of the secret) or as an ASCII
string (that means that the ASCII code of every character is interpreted
as one byte of the secret). As the HOTP RFC mentions both
representations, this implementation supports both.
|
|
|
|
|
|
|
| |
This patch implements the `otp get` subcommand that allows the user to
generate a one-time password on the Nitrokey device. Before generating
the password, the device configuration is checked so that the user only
has to enter a PIN if it is required for the OTP generation.
|
|
|
|
|
| |
This patch adds the `otp` top-level command. Its subcommands provide
access to one-time passwords on the Nitrokey.
|
|
|
|
|
|
| |
This patch implements authentication with the user or admin PIN. This
is a preparation for the `otp get` and `otp set` commands which require
user and admin access to the Nitrokey.
|
|
|
|
|
|
| |
Currently, we only clear the user PIN if clear is called. This patch
changes the clear command to also clear the admin PIN as we will start
to use the admin PIN in upcoming patches.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Currently, `open` directly calls the `pinentry` module and loops until
the user entered a correct passphrase or the retry limit is reached.
This patch moves the pinentry call and the loop into the
`try_with_passphrase_and_data` function. This function queries a
passphrase of a given type and executes a function with that passphrase.
This function has a data argument and may return data that is passed to
the next call of the function (if it failed).
This data-passing mechanism is required for the `nitrokey`
authentication functions: These functions take ownership of the device
and either return an authenticated device after successful
authentication, or an error including the unauthenticated device if the
authentication failed. This patch enables the usage of these functions
in future patches.
|
|
|
|
|
|
|
| |
Currently, invalid UTF-8 code points in the passphrase returned by
pinentry are replaced with replacement characters by
`String::from_utf8_lossy`. This patch changes the code to use
`String::from_utf8` and returns an UTF-8 error if encountered.
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
| |
Spaces in the arguments for gpg-connect-agent’s `GET_PASSPHRASE` command
have to be esaced using a plus sign. Somehow this was missing for the
prompt argument. This patch adds escaping for the prompt so that the
pinentry dialog is displayed correctly.
|