From b3a0db4508319b10a34a3b58c73369f2fdcd2e5d Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Sun, 23 Dec 2018 01:52:29 +0100 Subject: Implement otp command This patch adds the `otp` top-level command. Its subcommands provide access to one-time passwords on the Nitrokey. --- nitrocli/CHANGELOG.md | 1 + nitrocli/src/args.rs | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/nitrocli/CHANGELOG.md b/nitrocli/CHANGELOG.md index 2d43788..3ade4e3 100644 --- a/nitrocli/CHANGELOG.md +++ b/nitrocli/CHANGELOG.md @@ -6,6 +6,7 @@ Unreleased `nitrokey-sys` version `3.4.1` as well as `rand` version `0.4.3` as indirect dependencies - Removed the `hid`, `hidapi-sys` and `pkg-config` dependencies +- Added the `otp` command for working with one-time passwords - Enabled CI pipeline comprising code style conformance checks, linting, and building of the project - Added badges indicating pipeline status, current `crates.io` published diff --git a/nitrocli/src/args.rs b/nitrocli/src/args.rs index d4c3809..2112243 100644 --- a/nitrocli/src/args.rs +++ b/nitrocli/src/args.rs @@ -33,6 +33,7 @@ pub enum Command { Clear, Close, Open, + Otp, Status, } @@ -43,6 +44,7 @@ impl Command { Command::Clear => clear(args), Command::Close => close(args), Command::Open => open(args), + Command::Otp => otp(args), Command::Status => status(args), } } @@ -57,6 +59,7 @@ impl fmt::Display for Command { Command::Clear => "clear", Command::Close => "close", Command::Open => "open", + Command::Otp => "otp", Command::Status => "status", } ) @@ -71,12 +74,49 @@ impl str::FromStr for Command { "clear" => Ok(Command::Clear), "close" => Ok(Command::Close), "open" => Ok(Command::Open), + "otp" => Ok(Command::Otp), "status" => Ok(Command::Status), _ => Err(()), } } } +#[derive(Debug)] +enum OtpCommand { + Get, +} + +impl OtpCommand { + fn execute(&self, _args: Vec) -> Result<()> { + match *self { + OtpCommand::Get => Err(Error::Error("Not implementend".to_string())), + } + } +} + +impl fmt::Display for OtpCommand { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{}", + match *self { + OtpCommand::Get => "get", + } + ) + } +} + +impl str::FromStr for OtpCommand { + type Err = (); + + fn from_str(s: &str) -> std::result::Result { + match s { + "get" => Ok(OtpCommand::Get), + _ => Err(()), + } + } +} + fn parse(parser: &argparse::ArgumentParser<'_>, args: Vec) -> Result<()> { if let Err(err) = parser.parse(args, &mut io::stdout(), &mut io::stderr()) { Err(Error::ArgparseError(err)) @@ -121,6 +161,30 @@ fn clear(args: Vec) -> Result<()> { commands::clear() } +/// Execute an OTP subcommand. +fn otp(args: Vec) -> Result<()> { + let mut subcommand = OtpCommand::Get; + let mut subargs = vec![]; + let mut parser = argparse::ArgumentParser::new(); + parser.set_description("Accesses one-time passwords"); + let _ = parser.refer(&mut subcommand).required().add_argument( + "subcommand", + argparse::Store, + "The subcommand to execute (get)", + ); + 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 otp {}", subcommand)); + subcommand.execute(subargs) +} + /// Parse the command-line arguments and return the selected command and /// the remaining arguments for the command. fn parse_arguments(args: Vec) -> Result<(Command, Vec)> { @@ -131,7 +195,7 @@ fn parse_arguments(args: Vec) -> Result<(Command, Vec)> { let _ = parser.refer(&mut command).required().add_argument( "command", argparse::Store, - "The command to execute (clear|close|open|status)", + "The command to execute (clear|close|open|otp|status)", ); let _ = parser.refer(&mut subargs).add_argument( "arguments", -- cgit v1.2.1