summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Mueller <deso@posteo.net>2018-12-27 20:03:47 -0800
committerDaniel Mueller <deso@posteo.net>2018-12-27 20:03:47 -0800
commitc3b9df0dfa9ef2de2a800c4fbc5880a49da0d9bb (patch)
tree9bac2d47a56604becc27543c56fd8343317d9660
parent0148d954b1ea3105696e9958152b679997d9be86 (diff)
downloadnitrocli-c3b9df0dfa9ef2de2a800c4fbc5880a49da0d9bb.tar.gz
nitrocli-c3b9df0dfa9ef2de2a800c4fbc5880a49da0d9bb.tar.bz2
Make 'open' and 'close' subcommands of new 'storage' command
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'.
-rw-r--r--nitrocli/CHANGELOG.md2
-rw-r--r--nitrocli/README.md9
-rw-r--r--nitrocli/doc/nitrocli.119
-rw-r--r--nitrocli/src/args.rs88
-rw-r--r--nitrocli/src/commands.rs4
-rw-r--r--nitrocli/src/main.rs2
6 files changed, 95 insertions, 29 deletions
diff --git a/nitrocli/CHANGELOG.md b/nitrocli/CHANGELOG.md
index 682995a..813f853 100644
--- a/nitrocli/CHANGELOG.md
+++ b/nitrocli/CHANGELOG.md
@@ -8,6 +8,8 @@ Unreleased
- Removed the `hid`, `hidapi-sys` and `pkg-config` dependencies
- Added the `otp` command for working with one-time passwords
- Added the `config` command for reading and writing the device configuration
+- Moved `open` and `close` commands as subcommands into newly introduced
+ `storage` command
- Made `status` command work with Nitrokey Pro devices
- Enabled CI pipeline comprising code style conformance checks, linting,
and building of the project
diff --git a/nitrocli/README.md b/nitrocli/README.md
index 3e0b518..b28f09e 100644
--- a/nitrocli/README.md
+++ b/nitrocli/README.md
@@ -11,10 +11,11 @@ nitrocli
certain commands on the [Nitrokey Storage][nitrokey-storage] device.
The following commands are currently supported:
-- open: Open the encrypted volume. The user PIN needs to be entered.
-- close: Close the encrypted volume.
- status: Report status information about the Nitrokey.
- clear: Remove the user and admin PIN from gpg-agent's cache.
+- storage: Work with the Nitrokey's storage.
+ - open: Open the encrypted volume. The user PIN needs to be entered.
+ - close: Close the encrypted volume.
- otp: Access one-time passwords (OTP).
- get: Generate a one-time password.
- set: Set an OTP slot.
@@ -38,7 +39,7 @@ parameter (note that some commands are organized through subcommands,
which are required as well), e.g.:
```bash
# Open the nitrokey's encrypted volume.
-$ nitrocli open
+$ nitrocli storage open
$ nitrocli status
Status:
@@ -57,7 +58,7 @@ Status:
hidden: inactive
# Close it again.
-$ nitrocli close
+$ nitrocli storage close
```
diff --git a/nitrocli/doc/nitrocli.1 b/nitrocli/doc/nitrocli.1
index e345cdb..44d41fd 100644
--- a/nitrocli/doc/nitrocli.1
+++ b/nitrocli/doc/nitrocli.1
@@ -12,14 +12,6 @@ It can be used to access the encrypted volume and the one-time password generato
.SH COMMANDS
.SS General
.TP
-.B nitrocli open
-Open the encrypted volume on the Nitrokey Storage.
-The user PIN that is required to open the volume is queried using
-\fBpinentry\fR(1) and cached by \fBgpg-agent\fR(1).
-.TP
-.B nitrocli close
-Close the encrypted volume on the Nitrokey Storage.
-.TP
.B nitrocli status
Print the status of the connected Nitrokey device, including the stick serial
number, SD card serial number, the firmware version and the PIN retry count.
@@ -28,6 +20,17 @@ of the volumes.
.TP
.B nitrocli clear
Clear the passphrases cached by the other commands.
+
+.SS Storage
+.TP
+\fBnitrocli storage open
+Open the encrypted volume on the Nitrokey Storage.
+The user PIN that is required to open the volume is queried using
+\fBpinentry\fR(1) and cached by \fBgpg-agent\fR(1).
+.TP
+\fBnitrocli storage close
+Close the encrypted volume on the Nitrokey Storage.
+
.SS One-time passwords
.TP
\fBnitrocli otp get \fIslot \fR[\fB-a\fR|\fB--algorithm \fIalgorithm\fR]
diff --git a/nitrocli/src/args.rs b/nitrocli/src/args.rs
index 36da560..d7a6d25 100644
--- a/nitrocli/src/args.rs
+++ b/nitrocli/src/args.rs
@@ -31,11 +31,10 @@ type Result<T> = result::Result<T, Error>;
#[derive(Debug)]
pub enum Command {
Clear,
- Close,
Config,
- Open,
Otp,
Status,
+ Storage,
}
impl Command {
@@ -43,11 +42,10 @@ impl Command {
pub fn execute(&self, args: Vec<String>) -> Result<()> {
match *self {
Command::Clear => clear(args),
- Command::Close => close(args),
Command::Config => config(args),
- Command::Open => open(args),
Command::Otp => otp(args),
Command::Status => status(args),
+ Command::Storage => storage(args),
}
}
}
@@ -59,11 +57,10 @@ impl fmt::Display for Command {
"{}",
match *self {
Command::Clear => "clear",
- Command::Close => "close",
Command::Config => "config",
- Command::Open => "open",
Command::Otp => "otp",
Command::Status => "status",
+ Command::Storage => "storage",
}
)
}
@@ -75,11 +72,10 @@ impl str::FromStr for Command {
fn from_str(s: &str) -> result::Result<Self, Self::Err> {
match s {
"clear" => Ok(Command::Clear),
- "close" => Ok(Command::Close),
"config" => Ok(Command::Config),
- "open" => Ok(Command::Open),
"otp" => Ok(Command::Otp),
"status" => Ok(Command::Status),
+ "storage" => Ok(Command::Storage),
_ => Err(()),
}
}
@@ -297,24 +293,88 @@ fn status(args: Vec<String>) -> Result<()> {
}
/// Open the encrypted volume on the nitrokey.
-fn open(args: Vec<String>) -> Result<()> {
+fn storage_open(args: Vec<String>) -> Result<()> {
let mut parser = argparse::ArgumentParser::new();
parser.set_description("Opens the encrypted volume on a Nitrokey Storage");
parse(&parser, args)?;
- commands::open()
+ commands::storage_open()
}
/// Close the previously opened encrypted volume.
-fn close(args: Vec<String>) -> Result<()> {
+fn storage_close(args: Vec<String>) -> Result<()> {
let mut parser = argparse::ArgumentParser::new();
parser.set_description("Closes the encrypted volume on a Nitrokey Storage");
parse(&parser, args)?;
- commands::close()
+ commands::storage_close()
+}
+
+#[derive(Debug)]
+enum StorageCommand {
+ Close,
+ Open,
+}
+
+impl StorageCommand {
+ fn execute(&self, args: Vec<String>) -> Result<()> {
+ match *self {
+ StorageCommand::Close => storage_close(args),
+ StorageCommand::Open => storage_open(args),
+ }
+ }
+}
+
+impl fmt::Display for StorageCommand {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(
+ f,
+ "{}",
+ match *self {
+ StorageCommand::Close => "close",
+ StorageCommand::Open => "open",
+ }
+ )
+ }
+}
+
+impl str::FromStr for StorageCommand {
+ type Err = ();
+
+ fn from_str(s: &str) -> result::Result<Self, Self::Err> {
+ match s {
+ "close" => Ok(StorageCommand::Close),
+ "open" => Ok(StorageCommand::Open),
+ _ => Err(()),
+ }
+ }
+}
+
+/// Execute a storage subcommand.
+fn storage(args: Vec<String>) -> Result<()> {
+ let mut subcommand = StorageCommand::Open;
+ let mut subargs = vec![];
+ let mut parser = argparse::ArgumentParser::new();
+ parser.set_description("Interacts with the device's storage");
+ let _ = parser.refer(&mut subcommand).required().add_argument(
+ "subcommand",
+ argparse::Store,
+ "The subcommand to execute (open|close)",
+ );
+ let _ = parser.refer(&mut subargs).add_argument(
+ "arguments",
+ argparse::List,
+ "The arguments for the subcommand",
+ );
+ parser.stop_on_first_argument(true);
+ parse(&parser, args)?;
+ drop(parser);
+
+ subargs.insert(0, format!("nitrocli storage {}", subcommand));
+ subcommand.execute(subargs)
}
-/// Clear the PIN stored when opening the nitrokey's encrypted volume.
+/// Clear the PIN as cached by various other commands.
fn clear(args: Vec<String>) -> Result<()> {
let mut parser = argparse::ArgumentParser::new();
parser.set_description("Clears the cached passphrases");
@@ -584,7 +644,7 @@ fn parse_arguments(args: Vec<String>) -> Result<(Command, Vec<String>)> {
let _ = parser.refer(&mut command).required().add_argument(
"command",
argparse::Store,
- "The command to execute (clear|close|config|open|otp|status)",
+ "The command to execute (clear|config|otp|status|storage)",
);
let _ = parser.refer(&mut subargs).add_argument(
"arguments",
diff --git a/nitrocli/src/commands.rs b/nitrocli/src/commands.rs
index 9aef2de..fdfe049 100644
--- a/nitrocli/src/commands.rs
+++ b/nitrocli/src/commands.rs
@@ -243,7 +243,7 @@ pub fn status() -> Result<()> {
}
/// Open the encrypted volume on the nitrokey.
-pub fn open() -> Result<()> {
+pub fn storage_open() -> Result<()> {
let device = get_storage_device()?;
try_with_passphrase(
pinentry::PinType::User,
@@ -258,7 +258,7 @@ extern "C" {
}
/// Close the previously opened encrypted volume.
-pub fn close() -> Result<()> {
+pub fn storage_close() -> Result<()> {
// Flush all filesystem caches to disk. We are mostly interested in
// making sure that the encrypted volume on the nitrokey we are
// about to close is not closed while not all data was written to
diff --git a/nitrocli/src/main.rs b/nitrocli/src/main.rs
index 8a20494..4f39fdb 100644
--- a/nitrocli/src/main.rs
+++ b/nitrocli/src/main.rs
@@ -66,7 +66,7 @@
)]
//! Nitrocli is a program providing a command line interface to certain
-//! commands of the Nitrokey Storage device.
+//! commands of Nitrokey Pro and Storage devices.
mod args;
mod commands;