aboutsummaryrefslogtreecommitdiff
path: root/nitrocli/src/args.rs
diff options
context:
space:
mode:
Diffstat (limited to 'nitrocli/src/args.rs')
-rw-r--r--nitrocli/src/args.rs112
1 files changed, 111 insertions, 1 deletions
diff --git a/nitrocli/src/args.rs b/nitrocli/src/args.rs
index f4035e6..c27fbc2 100644
--- a/nitrocli/src/args.rs
+++ b/nitrocli/src/args.rs
@@ -84,12 +84,14 @@ impl str::FromStr for Command {
#[derive(Debug)]
enum OtpCommand {
Get,
+ Set,
}
impl OtpCommand {
fn execute(&self, args: Vec<String>) -> Result<()> {
match *self {
OtpCommand::Get => otp_get(args),
+ OtpCommand::Set => otp_set(args),
}
}
}
@@ -101,6 +103,7 @@ impl fmt::Display for OtpCommand {
"{}",
match *self {
OtpCommand::Get => "get",
+ OtpCommand::Set => "set",
}
)
}
@@ -112,6 +115,7 @@ impl str::FromStr for OtpCommand {
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
match s {
"get" => Ok(OtpCommand::Get),
+ "set" => Ok(OtpCommand::Set),
_ => Err(()),
}
}
@@ -148,6 +152,46 @@ impl str::FromStr for OtpAlgorithm {
}
}
+#[derive(Clone, Copy, Debug)]
+enum OtpMode {
+ SixDigits,
+ EightDigits,
+}
+
+impl fmt::Display for OtpMode {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(
+ f,
+ "{}",
+ match *self {
+ OtpMode::SixDigits => "6",
+ OtpMode::EightDigits => "8",
+ }
+ )
+ }
+}
+
+impl str::FromStr for OtpMode {
+ type Err = ();
+
+ fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
+ match s {
+ "6" => Ok(OtpMode::SixDigits),
+ "8" => Ok(OtpMode::EightDigits),
+ _ => Err(()),
+ }
+ }
+}
+
+impl From<OtpMode> for nitrokey::OtpMode {
+ fn from(mode: OtpMode) -> Self {
+ match mode {
+ OtpMode::SixDigits => nitrokey::OtpMode::SixDigits,
+ OtpMode::EightDigits => nitrokey::OtpMode::EightDigits,
+ }
+ }
+}
+
fn parse(parser: &argparse::ArgumentParser<'_>, args: Vec<String>) -> Result<()> {
if let Err(err) = parser.parse(args, &mut io::stdout(), &mut io::stderr()) {
Err(Error::ArgparseError(err))
@@ -201,7 +245,7 @@ fn otp(args: Vec<String>) -> Result<()> {
let _ = parser.refer(&mut subcommand).required().add_argument(
"subcommand",
argparse::Store,
- "The subcommand to execute (get)",
+ "The subcommand to execute (get|set)",
);
let _ = parser.refer(&mut subargs).add_argument(
"arguments",
@@ -238,6 +282,72 @@ fn otp_get(args: Vec<String>) -> Result<()> {
commands::otp_get(slot, algorithm)
}
+/// Configure a one-time password slot on the Nitrokey device.
+pub fn otp_set(args: Vec<String>) -> Result<()> {
+ let mut slot: u8 = 0;
+ let mut algorithm = OtpAlgorithm::Totp;
+ let mut name = "".to_owned();
+ let mut secret = "".to_owned();
+ let mut digits = OtpMode::SixDigits;
+ let mut counter: u64 = 0;
+ let mut time_window: u16 = 30;
+ let mut ascii = false;
+ let mut parser = argparse::ArgumentParser::new();
+ parser.set_description("Configures a one-time password slot");
+ let _ =
+ parser
+ .refer(&mut slot)
+ .required()
+ .add_argument("slot", argparse::Store, "The OTP slot to use");
+ let _ = parser.refer(&mut algorithm).add_option(
+ &["-a", "--algorithm"],
+ argparse::Store,
+ "The OTP algorithm to use (hotp or totp, default: totp",
+ );
+ let _ = parser.refer(&mut name).required().add_argument(
+ "name",
+ argparse::Store,
+ "The name of the slot",
+ );
+ let _ = parser.refer(&mut secret).required().add_argument(
+ "secret",
+ argparse::Store,
+ "The secret to store on the slot as a hexadecimal string (unless --ascii is set)",
+ );
+ let _ = parser.refer(&mut digits).add_option(
+ &["-d", "--digits"],
+ argparse::Store,
+ "The number of digits to use for the one-time password (6 or 8, default: 6)",
+ );
+ let _ = parser.refer(&mut counter).add_option(
+ &["-c", "--counter"],
+ argparse::Store,
+ "The counter value for HOTP (default: 0)",
+ );
+ let _ = parser.refer(&mut time_window).add_option(
+ &["-t", "--time-window"],
+ argparse::Store,
+ "The time window for TOTP (default: 30)",
+ );
+ let _ = parser.refer(&mut ascii).add_option(
+ &["--ascii"],
+ argparse::StoreTrue,
+ "Interpret the given secret as an ASCII string of the secret",
+ );
+ parse(&parser, args)?;
+ drop(parser);
+
+ let data = nitrokey::OtpSlotData {
+ number: slot,
+ name,
+ secret,
+ mode: nitrokey::OtpMode::from(digits),
+ use_enter: false,
+ token_id: None,
+ };
+ commands::otp_set(data, algorithm, counter, time_window, ascii)
+}
+
/// Parse the command-line arguments and return the selected command and
/// the remaining arguments for the command.
fn parse_arguments(args: Vec<String>) -> Result<(Command, Vec<String>)> {